From ecca3294140e8af6c5d28c0195d8f4cc61bdb43a Mon Sep 17 00:00:00 2001 From: Domen Mori Date: Sat, 29 Aug 2020 21:12:15 +0200 Subject: [PATCH 1/4] Win32 global hotkeys MVP --- configure.ac | 15 + src/hotkey/Makefile | 2 +- src/hotkey/api_hotkey.h | 59 +++ src/hotkey/grab.cc | 403 ++++++++++--------- src/hotkey/gui.cc | 594 +++++++++++----------------- src/hotkey/hotkey_api_common.cc | 103 +++++ src/hotkey/plugin.cc | 294 +++++++------- src/hotkey/plugin.h | 44 ++- src/hotkey/x_hotkey.cc | 37 ++ src/hotkeyw32/Makefile | 13 + src/hotkeyw32/w32_grab.cc | 20 + src/hotkeyw32/w32_hotkey.cc | 305 ++++++++++++++ src/hotkeyw32/windows_key_str_map.h | 266 +++++++++++++ 13 files changed, 1420 insertions(+), 735 deletions(-) create mode 100644 src/hotkey/api_hotkey.h create mode 100644 src/hotkey/hotkey_api_common.cc create mode 100644 src/hotkey/x_hotkey.cc create mode 100644 src/hotkeyw32/Makefile create mode 100644 src/hotkeyw32/w32_grab.cc create mode 100644 src/hotkeyw32/w32_hotkey.cc create mode 100644 src/hotkeyw32/windows_key_str_map.h diff --git a/configure.ac b/configure.ac index 7d773c7eea..6a447c2a6b 100644 --- a/configure.ac +++ b/configure.ac @@ -483,6 +483,20 @@ ENABLE_PLUGIN_WITH_DEP(hotkey, GDKX11, gdk-x11-2.0) + +test_hotkeyw32 () { + if test $HAVE_MSWINDOWS = yes ; then + have_hotkeyw32=yes + else + have_hotkeyw32=no + fi + } + +ENABLE_PLUGIN_WITH_TEST(hotkeyw32, + Windows hotkeys plugin, + auto, + GENERAL) + ENABLE_PLUGIN_WITH_DEP(aosd, X11 OSD, auto, @@ -834,6 +848,7 @@ if test "x$USE_GTK" = "xyes" ; then echo " Status Icon: yes" echo " X11 Global Hotkeys: $have_hotkey" echo " X11 On-Screen Display (aosd): $have_aosd" + echo " Windows Global hotkeys: $have_hotkeyw32" echo fi diff --git a/src/hotkey/Makefile b/src/hotkey/Makefile index 3765d51bd7..74137df663 100644 --- a/src/hotkey/Makefile +++ b/src/hotkey/Makefile @@ -1,6 +1,6 @@ PLUGIN = hotkey${PLUGIN_SUFFIX} -SRCS = plugin.cc gui.cc grab.cc +SRCS = plugin.cc gui.cc grab.cc x_hotkey.cc hotkey_api_common.cc include ../../buildsys.mk include ../../extra.mk diff --git a/src/hotkey/api_hotkey.h b/src/hotkey/api_hotkey.h new file mode 100644 index 0000000000..1c6e99723d --- /dev/null +++ b/src/hotkey/api_hotkey.h @@ -0,0 +1,59 @@ +#ifndef _X_HOTKEY_H_INCLUDED +#define _X_HOTKEY_H_INCLUDED + +#include +#include +#ifndef _WIN32 +#include +#include +#endif +#include "plugin.h" + + + +class Hotkey { + +//#ifdef _WIN32 +//#define OS_KeySym int +//#else +//#define OS_KeySym KeySym +//#endif + +#ifdef _WIN32 + typedef int OS_KeySym; +#else + typedef KeySym OS_KeySym; +#endif + + public: + static void set_keytext(GtkWidget *entry, int key, int mask, int type); + static std::pair get_is_mod(GdkEventKey *event); + template + static int calculate_mod(T_GDK_EVENT *event); + static void add_hotkey(HotkeyConfiguration **pphotkey, OS_KeySym keysym, int mask, int type, EVENT event); + static void key_to_string(int key, char **out_keytext); +}; + +#ifndef _WIN32 +#define OS_KEY_AudioPrev XF86XK_AudioPrev +#define OS_KEY_AudioPlay XF86XK_AudioPlay +#define OS_KEY_AudioPause XF86XK_AudioPause +#define OS_KEY_AudioStop XF86XK_AudioStop +#define OS_KEY_AudioNext XF86XK_AudioNext +#define OS_KEY_AudioMute XF86XK_AudioMute +#define OS_KEY_AudioRaiseVolume XF86XK_AudioRaiseVolume +#define OS_KEY_AudioLowerVolume XF86XK_AudioLowerVolume +#else + +#define OS_KEY_AudioPrev 0 +#define OS_KEY_AudioPlay 0 +#define OS_KEY_AudioPause 0 +#define OS_KEY_AudioStop 0 +#define OS_KEY_AudioNext 0 +#define OS_KEY_AudioMute 0 +#define OS_KEY_AudioRaiseVolume 0 +#define OS_KEY_AudioLowerVolume 0 + +#endif + +#endif //_X_HOTKEY_H_INCLUDED diff --git a/src/hotkey/grab.cc b/src/hotkey/grab.cc index febb96b34a..ffcad21bc2 100644 --- a/src/hotkey/grab.cc +++ b/src/hotkey/grab.cc @@ -30,39 +30,130 @@ * * You should have received a copy of the GNU General Public License * along with audacious-hotkey; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include #include +#ifndef _WIN32 +#include +#else +#include +#include +#include +#endif + #include "grab.h" #include "plugin.h" + static int grabbed = 0; static unsigned int numlock_mask = 0; static unsigned int scrolllock_mask = 0; static unsigned int capslock_mask = 0; + +static int x11_error_handler (Display *dpy, XErrorEvent *error) +{ + return 0; +} + +static GdkFilterReturn +gdk_filter(GdkXEvent *xevent, + GdkEvent *event, + void * data) +{ +#ifdef _WIN32 + AUDDBG("lHotkeyFlow:win CommonGrab: Filter trigger."); + assert(false); +#endif + HotkeyConfiguration *hotkey; + hotkey = &(get_config()->first); + switch (((XEvent*)xevent)->type) + { + case KeyPress: + { + XKeyEvent *keyevent = (XKeyEvent*)xevent; + while (hotkey) + { + if ((hotkey->key == keyevent->keycode) && + (hotkey->mask == (keyevent->state & ~(scrolllock_mask | numlock_mask | capslock_mask))) && + (hotkey->type == TYPE_KEY)) + { + if (handle_keyevent(hotkey->event)) + return GDK_FILTER_REMOVE; + break; + } + + hotkey = hotkey->next; + } + break; + } + case ButtonPress: + { + XButtonEvent *buttonevent = (XButtonEvent*)xevent; + while (hotkey) + { + if ((hotkey->key == buttonevent->button) && + (hotkey->mask == (buttonevent->state & ~(scrolllock_mask | numlock_mask | capslock_mask))) && + (hotkey->type == TYPE_MOUSE)) + { + if (handle_keyevent(hotkey->event)) + return GDK_FILTER_REMOVE; + break; + } + + hotkey = hotkey->next; + } + + break; + } + } + + return GDK_FILTER_CONTINUE; +} + +gboolean setup_filter() +{ +#ifdef _WIN32 + AUDDBG("lHotkeyFlow:win CommonGrab: filter up"); +#endif + gdk_window_add_filter (gdk_screen_get_root_window + (gdk_screen_get_default ()), gdk_filter, nullptr); + + return true; +} + +void release_filter() +{ +#ifdef _WIN32 + AUDDBG("lHotkeyFlow:win CommonGrab: down filter"); +#endif + gdk_window_remove_filter (gdk_screen_get_root_window + (gdk_screen_get_default ()), gdk_filter, nullptr); +} + +#ifndef _WIN32 /* Taken from xbindkeys */ -static void get_offending_modifiers(Display * dpy) +static void get_offending_modifiers (Display * dpy) { int i; - XModifierKeymap * modmap; + XModifierKeymap *modmap; KeyCode nlock, slock; - static int mask_table[8] = {ShiftMask, LockMask, ControlMask, Mod1Mask, - Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask}; + static int mask_table[8] = { + HK_SHIFT_MASK, LockMask, HK_CONTROL_MASK, HK_MOD1_ALT_MASK, + HK_MOD2_MASK, HK_MOD3_MASK, HK_MOD4_MASK, HK_MOD5_MASK + }; - nlock = XKeysymToKeycode(dpy, XK_Num_Lock); - slock = XKeysymToKeycode(dpy, XK_Scroll_Lock); + nlock = XKeysymToKeycode (dpy, XK_Num_Lock); + slock = XKeysymToKeycode (dpy, XK_Scroll_Lock); /* - * Find out the masks for the NumLock and ScrollLock modifiers, - * so that we can bind the grabs for when they are enabled too. - */ - modmap = XGetModifierMapping(dpy); + * Find out the masks for the NumLock and ScrollLock modifiers, + * so that we can bind the grabs for when they are enabled too. + */ + modmap = XGetModifierMapping (dpy); if (modmap != nullptr && modmap->max_keypermod > 0) { @@ -78,132 +169,127 @@ static void get_offending_modifiers(Display * dpy) capslock_mask = LockMask; if (modmap) - XFreeModifiermap(modmap); + XFreeModifiermap (modmap); } -static int x11_error_handler(Display * dpy, XErrorEvent * error) { return 0; } - /* grab required keys */ -static void grab_key(const HotkeyConfiguration * hotkey, Display * xdisplay, - Window x_root_window) +static void grab_key(const HotkeyConfiguration *hotkey, Display *xdisplay, Window x_root_window) { - unsigned int modifier = - hotkey->mask & ~(numlock_mask | capslock_mask | scrolllock_mask); + unsigned int modifier = hotkey->mask & ~(numlock_mask | capslock_mask | scrolllock_mask); - if (hotkey->key == 0) - return; + if (hotkey->key == 0) return; if (hotkey->type == TYPE_KEY) { - XGrabKey(xdisplay, hotkey->key, modifier, x_root_window, False, - GrabModeAsync, GrabModeAsync); + XGrabKey (xdisplay, hotkey->key, modifier, x_root_window, + False, GrabModeAsync, GrabModeAsync); if (modifier == AnyModifier) return; if (numlock_mask) - XGrabKey(xdisplay, hotkey->key, modifier | numlock_mask, - x_root_window, False, GrabModeAsync, GrabModeAsync); + XGrabKey (xdisplay, hotkey->key, modifier | numlock_mask, + x_root_window, + False, GrabModeAsync, GrabModeAsync); if (capslock_mask) - XGrabKey(xdisplay, hotkey->key, modifier | capslock_mask, - x_root_window, False, GrabModeAsync, GrabModeAsync); + XGrabKey (xdisplay, hotkey->key, modifier | capslock_mask, + x_root_window, + False, GrabModeAsync, GrabModeAsync); if (scrolllock_mask) - XGrabKey(xdisplay, hotkey->key, modifier | scrolllock_mask, - x_root_window, False, GrabModeAsync, GrabModeAsync); + XGrabKey (xdisplay, hotkey->key, modifier | scrolllock_mask, + x_root_window, + False, GrabModeAsync, GrabModeAsync); if (numlock_mask && capslock_mask) - XGrabKey(xdisplay, hotkey->key, - modifier | numlock_mask | capslock_mask, x_root_window, - False, GrabModeAsync, GrabModeAsync); + XGrabKey (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask, + x_root_window, + False, GrabModeAsync, GrabModeAsync); if (numlock_mask && scrolllock_mask) - XGrabKey(xdisplay, hotkey->key, - modifier | numlock_mask | scrolllock_mask, x_root_window, - False, GrabModeAsync, GrabModeAsync); + XGrabKey (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask, + x_root_window, + False, GrabModeAsync, GrabModeAsync); if (capslock_mask && scrolllock_mask) - XGrabKey(xdisplay, hotkey->key, - modifier | capslock_mask | scrolllock_mask, x_root_window, - False, GrabModeAsync, GrabModeAsync); + XGrabKey (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask, + x_root_window, + False, GrabModeAsync, GrabModeAsync); if (numlock_mask && capslock_mask && scrolllock_mask) - XGrabKey(xdisplay, hotkey->key, - modifier | numlock_mask | capslock_mask | scrolllock_mask, - x_root_window, False, GrabModeAsync, GrabModeAsync); + XGrabKey (xdisplay, hotkey->key, + modifier | numlock_mask | capslock_mask | scrolllock_mask, + x_root_window, False, GrabModeAsync, + GrabModeAsync); } if (hotkey->type == TYPE_MOUSE) { - XGrabButton(xdisplay, hotkey->key, modifier, x_root_window, False, - ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + XGrabButton (xdisplay, hotkey->key, modifier, x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); if (modifier == AnyModifier) return; if (numlock_mask) - XGrabButton(xdisplay, hotkey->key, modifier | numlock_mask, - x_root_window, False, ButtonPressMask, GrabModeAsync, - GrabModeAsync, None, None); + XGrabButton (xdisplay, hotkey->key, modifier | numlock_mask, + x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); if (capslock_mask) - XGrabButton(xdisplay, hotkey->key, modifier | capslock_mask, - x_root_window, False, ButtonPressMask, GrabModeAsync, - GrabModeAsync, None, None); + XGrabButton (xdisplay, hotkey->key, modifier | capslock_mask, + x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); if (scrolllock_mask) - XGrabButton(xdisplay, hotkey->key, modifier | scrolllock_mask, - x_root_window, False, ButtonPressMask, GrabModeAsync, - GrabModeAsync, None, None); + XGrabButton (xdisplay, hotkey->key, modifier | scrolllock_mask, + x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); if (numlock_mask && capslock_mask) - XGrabButton(xdisplay, hotkey->key, - modifier | numlock_mask | capslock_mask, x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, - None, None); + XGrabButton (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask, + x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); if (numlock_mask && scrolllock_mask) - XGrabButton(xdisplay, hotkey->key, - modifier | numlock_mask | scrolllock_mask, - x_root_window, False, ButtonPressMask, GrabModeAsync, - GrabModeAsync, None, None); + XGrabButton (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask, + x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); if (capslock_mask && scrolllock_mask) - XGrabButton(xdisplay, hotkey->key, - modifier | capslock_mask | scrolllock_mask, - x_root_window, False, ButtonPressMask, GrabModeAsync, - GrabModeAsync, None, None); + XGrabButton (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask, + x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); if (numlock_mask && capslock_mask && scrolllock_mask) - XGrabButton(xdisplay, hotkey->key, - modifier | numlock_mask | capslock_mask | - scrolllock_mask, - x_root_window, False, ButtonPressMask, GrabModeAsync, - GrabModeAsync, None, None); + XGrabButton (xdisplay, hotkey->key, + modifier | numlock_mask | capslock_mask | scrolllock_mask, + x_root_window, False, ButtonPressMask, GrabModeAsync, + GrabModeAsync, None, None); } } -void grab_keys() +void grab_keys ( ) { - Display * xdisplay; + Display* xdisplay; int screen; - PluginConfig * plugin_cfg = get_config(); - HotkeyConfiguration * hotkey; + PluginConfig* plugin_cfg = get_config(); + HotkeyConfiguration *hotkey; XErrorHandler old_handler = 0; - xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + + if (grabbed) return; - if (grabbed) - return; XSync(xdisplay, False); - old_handler = XSetErrorHandler(x11_error_handler); + old_handler = XSetErrorHandler (x11_error_handler); get_offending_modifiers(xdisplay); hotkey = &(plugin_cfg->first); while (hotkey) { - for (screen = 0; screen < ScreenCount(xdisplay); screen++) + for (screen=0;screenmask & ~(numlock_mask | capslock_mask | scrolllock_mask); + unsigned int modifier = hotkey->mask & ~(numlock_mask | capslock_mask | scrolllock_mask); - if (hotkey->key == 0) - return; + if (hotkey->key == 0) return; if (hotkey->type == TYPE_KEY) { - XUngrabKey(xdisplay, hotkey->key, modifier, x_root_window); + XUngrabKey (xdisplay, hotkey->key, modifier, x_root_window); if (modifier == AnyModifier) return; if (numlock_mask) - XUngrabKey(xdisplay, hotkey->key, modifier | numlock_mask, - x_root_window); + XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask, x_root_window); if (capslock_mask) - XUngrabKey(xdisplay, hotkey->key, modifier | capslock_mask, - x_root_window); + XUngrabKey (xdisplay, hotkey->key, modifier | capslock_mask, x_root_window); if (scrolllock_mask) - XUngrabKey(xdisplay, hotkey->key, modifier | scrolllock_mask, - x_root_window); + XUngrabKey (xdisplay, hotkey->key, modifier | scrolllock_mask, x_root_window); if (numlock_mask && capslock_mask) - XUngrabKey(xdisplay, hotkey->key, - modifier | numlock_mask | capslock_mask, x_root_window); + XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask, x_root_window); if (numlock_mask && scrolllock_mask) - XUngrabKey(xdisplay, hotkey->key, - modifier | numlock_mask | scrolllock_mask, - x_root_window); + XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask, x_root_window); if (capslock_mask && scrolllock_mask) - XUngrabKey(xdisplay, hotkey->key, - modifier | capslock_mask | scrolllock_mask, - x_root_window); + XUngrabKey (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask, x_root_window); if (numlock_mask && capslock_mask && scrolllock_mask) - XUngrabKey(xdisplay, hotkey->key, - modifier | numlock_mask | capslock_mask | - scrolllock_mask, - x_root_window); + XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window); } if (hotkey->type == TYPE_MOUSE) { - XUngrabButton(xdisplay, hotkey->key, modifier, x_root_window); + XUngrabButton (xdisplay, hotkey->key, modifier, x_root_window); if (modifier == AnyModifier) return; if (numlock_mask) - XUngrabButton(xdisplay, hotkey->key, modifier | numlock_mask, - x_root_window); + XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask, x_root_window); if (capslock_mask) - XUngrabButton(xdisplay, hotkey->key, modifier | capslock_mask, - x_root_window); + XUngrabButton (xdisplay, hotkey->key, modifier | capslock_mask, x_root_window); if (scrolllock_mask) - XUngrabButton(xdisplay, hotkey->key, modifier | scrolllock_mask, - x_root_window); + XUngrabButton (xdisplay, hotkey->key, modifier | scrolllock_mask, x_root_window); if (numlock_mask && capslock_mask) - XUngrabButton(xdisplay, hotkey->key, - modifier | numlock_mask | capslock_mask, - x_root_window); + XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask, x_root_window); if (numlock_mask && scrolllock_mask) - XUngrabButton(xdisplay, hotkey->key, - modifier | numlock_mask | scrolllock_mask, - x_root_window); + XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask, x_root_window); if (capslock_mask && scrolllock_mask) - XUngrabButton(xdisplay, hotkey->key, - modifier | capslock_mask | scrolllock_mask, - x_root_window); + XUngrabButton (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask, x_root_window); if (numlock_mask && capslock_mask && scrolllock_mask) - XUngrabButton(xdisplay, hotkey->key, - modifier | numlock_mask | capslock_mask | - scrolllock_mask, - x_root_window); + XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window); } } -void ungrab_keys() +void ungrab_keys ( ) { - Display * xdisplay; + Display* xdisplay; int screen; - PluginConfig * plugin_cfg = get_config(); - HotkeyConfiguration * hotkey; + PluginConfig* plugin_cfg = get_config(); + HotkeyConfiguration *hotkey; XErrorHandler old_handler = 0; - xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); - if (!grabbed) - return; - if (!xdisplay) - return; + if (!grabbed) return; + if (!xdisplay) return; XSync(xdisplay, False); - old_handler = XSetErrorHandler(x11_error_handler); + old_handler = XSetErrorHandler (x11_error_handler); get_offending_modifiers(xdisplay); hotkey = &(plugin_cfg->first); while (hotkey) { - for (screen = 0; screen < ScreenCount(xdisplay); screen++) + for (screen=0;screenfirst); - switch (((XEvent *)xevent)->type) - { - case KeyPress: - { - XKeyEvent * keyevent = (XKeyEvent *)xevent; - while (hotkey) - { - if ((hotkey->key == keyevent->keycode) && - (hotkey->mask == - (keyevent->state & - ~(scrolllock_mask | numlock_mask | capslock_mask))) && - (hotkey->type == TYPE_KEY)) - { - if (handle_keyevent(hotkey->event)) - return GDK_FILTER_REMOVE; - break; - } - - hotkey = hotkey->next; - } - break; - } - case ButtonPress: - { - XButtonEvent * buttonevent = (XButtonEvent *)xevent; - while (hotkey) - { - if ((hotkey->key == buttonevent->button) && - (hotkey->mask == - (buttonevent->state & - ~(scrolllock_mask | numlock_mask | capslock_mask))) && - (hotkey->type == TYPE_MOUSE)) - { - if (handle_keyevent(hotkey->event)) - return GDK_FILTER_REMOVE; - break; - } - - hotkey = hotkey->next; - } - - break; - } - } - - return GDK_FILTER_CONTINUE; -} - -gboolean setup_filter() -{ - gdk_window_add_filter(gdk_screen_get_root_window(gdk_screen_get_default()), - gdk_filter, nullptr); - - return true; -} - -void release_filter() -{ - gdk_window_remove_filter( - gdk_screen_get_root_window(gdk_screen_get_default()), gdk_filter, - nullptr); -} +#endif \ No newline at end of file diff --git a/src/hotkey/gui.cc b/src/hotkey/gui.cc index a4d940f0ea..454739797e 100644 --- a/src/hotkey/gui.cc +++ b/src/hotkey/gui.cc @@ -30,8 +30,7 @@ * * You should have received a copy of the GNU General Public License * along with audacious-hotkey; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include @@ -39,33 +38,35 @@ #include -#include -#include #include +#include -#include +#include +#include +#include "api_hotkey.h" #include "grab.h" #include "gui.h" #include "plugin.h" -typedef struct _KeyControls -{ - GtkWidget * keytext; - GtkWidget * grid; - GtkWidget * button; - GtkWidget * combobox; +typedef struct _KeyControls { + GtkWidget *keytext; + GtkWidget *grid; + GtkWidget *button; + GtkWidget *combobox; HotkeyConfiguration hotkey; struct _KeyControls *next, *prev, *first; } KeyControls; -static KeyControls * first_controls; +static KeyControls *first_controls; + + +static void clear_keyboard (GtkWidget *widget, void * data); +static void add_callback (GtkWidget *widget, void * data); +static void destroy_callback (); +static void ok_callback (); -static void clear_keyboard(GtkWidget * widget, void * data); -static void add_callback(GtkWidget * widget, void * data); -static void destroy_callback(); -static void ok_callback(); static const char * event_desc[EVENT_MAX] = { [EVENT_PREV_TRACK] = N_("Previous track"), @@ -84,222 +85,104 @@ static const char * event_desc[EVENT_MAX] = { [EVENT_TOGGLE_REPEAT] = N_("Toggle repeat"), [EVENT_TOGGLE_SHUFFLE] = N_("Toggle shuffle"), [EVENT_TOGGLE_STOP] = N_("Toggle stop after current"), - [EVENT_RAISE] = N_("Raise player window(s)")}; - -static void set_keytext(GtkWidget * entry, int key, int mask, int type) -{ - char * text = nullptr; - - if (key == 0 && mask == 0) - { - text = g_strdup(_("(none)")); - } - else - { - static const char * modifier_string[] = { - "Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5"}; - static const unsigned int modifiers[] = { - ControlMask, ShiftMask, Mod1Mask, Mod2Mask, - Mod3Mask, Mod4Mask, Mod5Mask}; - const char * strings[9]; - char * keytext = nullptr; - int i, j; - if (type == TYPE_KEY) - { - KeySym keysym; - keysym = XkbKeycodeToKeysym( - GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), key, 0, 0); - if (keysym == 0 || keysym == NoSymbol) - { - keytext = g_strdup_printf("#%d", key); - } - else - { - keytext = g_strdup(XKeysymToString(keysym)); - } - } - if (type == TYPE_MOUSE) - { - keytext = g_strdup_printf("Button%d", key); - } + [EVENT_RAISE] = N_("Raise player window(s)") +}; - for (i = 0, j = 0; j < 7; j++) - { - if (mask & modifiers[j]) - strings[i++] = modifier_string[j]; - } - if (key != 0) - strings[i++] = keytext; - strings[i] = nullptr; - - text = g_strjoinv(" + ", (char **)strings); - g_free(keytext); - } - - gtk_entry_set_text(GTK_ENTRY(entry), text); - gtk_editable_set_position(GTK_EDITABLE(entry), -1); - if (text) - g_free(text); -} - -static gboolean on_entry_key_press_event(GtkWidget * widget, - GdkEventKey * event, void * user_data) +static gboolean +on_entry_key_press_event(GtkWidget * widget, + GdkEventKey * event, + void * user_data) { - KeyControls * controls = (KeyControls *)user_data; - int is_mod; - int mod; + AUDDBG("lHotkeyFlow:Entry"); + KeyControls *controls = (KeyControls*) user_data; - if (event->keyval == GDK_Tab) - return false; - if (event->keyval == GDK_Escape && ((event->state & ~GDK_LOCK_MASK) == 0)) - return false; - if (event->keyval == GDK_Return && ((event->state & ~GDK_LOCK_MASK) == 0)) - return false; + if (event->keyval == GDK_Tab) return false; + if (event->keyval == GDK_Escape && ((event->state & ~GDK_LOCK_MASK) == 0)) return false; + if (event->keyval == GDK_Return && ((event->state & ~GDK_LOCK_MASK) == 0)) return false; if (event->keyval == GDK_ISO_Left_Tab) { - set_keytext(controls->keytext, controls->hotkey.key, - controls->hotkey.mask, controls->hotkey.type); + Hotkey::set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); return false; } - if (event->keyval == GDK_Up && ((event->state & ~GDK_LOCK_MASK) == 0)) - return false; - if (event->keyval == GDK_Down && ((event->state & ~GDK_LOCK_MASK) == 0)) - return false; - - mod = 0; - is_mod = 0; - - if ((event->state & GDK_CONTROL_MASK) | - (!is_mod && (is_mod = (event->keyval == GDK_Control_L || - event->keyval == GDK_Control_R)))) - mod |= ControlMask; + if (event->keyval == GDK_Up && ((event->state & ~GDK_LOCK_MASK) == 0)) return false; + if (event->keyval == GDK_Down && ((event->state & ~GDK_LOCK_MASK) == 0)) return false; - if ((event->state & GDK_MOD1_MASK) | - (!is_mod && - (is_mod = (event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_R)))) - mod |= Mod1Mask; + int mod, is_mod; + std::tie(mod, is_mod) = Hotkey::get_is_mod(event); - if ((event->state & GDK_SHIFT_MASK) | - (!is_mod && (is_mod = (event->keyval == GDK_Shift_L || - event->keyval == GDK_Shift_R)))) - mod |= ShiftMask; - - if ((event->state & GDK_MOD5_MASK) | - (!is_mod && (is_mod = (event->keyval == GDK_ISO_Level3_Shift)))) - mod |= Mod5Mask; - - if ((event->state & GDK_MOD4_MASK) | - (!is_mod && (is_mod = (event->keyval == GDK_Super_L || - event->keyval == GDK_Super_R)))) - mod |= Mod4Mask; - - if (!is_mod) - { - controls->hotkey.key = event->hardware_keycode; - controls->hotkey.mask = mod; - controls->hotkey.type = TYPE_KEY; - if (controls->next == nullptr) - add_callback(nullptr, (void *)controls); - else - gtk_widget_grab_focus(GTK_WIDGET(controls->next->keytext)); - } + if (!is_mod) { + controls->hotkey.key = event->hardware_keycode; + controls->hotkey.mask = mod; + controls->hotkey.type = TYPE_KEY; + if (controls->next == nullptr) + add_callback(nullptr, (void *) controls); + else gtk_widget_grab_focus(GTK_WIDGET(controls->next->keytext)); + } - set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod, - TYPE_KEY); + Hotkey::set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod, TYPE_KEY); + AUDDBG("lHotkeyFlow:Leave"); return true; } -static gboolean on_entry_key_release_event(GtkWidget * widget, - GdkEventKey * event, - void * user_data) +static gboolean +on_entry_key_release_event(GtkWidget * widget, + GdkEventKey * event, + void * user_data) { - KeyControls * controls = (KeyControls *)user_data; - if (!gtk_widget_is_focus(widget)) - return false; - set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, - controls->hotkey.type); + KeyControls *controls = (KeyControls*) user_data; + if (!gtk_widget_is_focus(widget)) return false; + Hotkey::set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); return true; } -static gboolean on_entry_button_press_event(GtkWidget * widget, - GdkEventButton * event, - void * user_data) +static gboolean +on_entry_button_press_event(GtkWidget * widget, + GdkEventButton * event, + void * user_data) { - KeyControls * controls = (KeyControls *)user_data; - int mod; - - if (!gtk_widget_is_focus(widget)) - return false; - - mod = 0; - if (event->state & GDK_CONTROL_MASK) - mod |= ControlMask; - - if (event->state & GDK_MOD1_MASK) - mod |= Mod1Mask; + KeyControls *controls = (KeyControls*) user_data; - if (event->state & GDK_SHIFT_MASK) - mod |= ShiftMask; + if (!gtk_widget_is_focus(widget)) return false; - if (event->state & GDK_MOD5_MASK) - mod |= Mod5Mask; - - if (event->state & GDK_MOD4_MASK) - mod |= Mod4Mask; + int mod = Hotkey::calculate_mod(event); if ((event->button <= 3) && (mod == 0)) { - GtkWidget * dialog; + GtkWidget* dialog; int response; - dialog = gtk_message_dialog_new( - GTK_WINDOW(gtk_widget_get_toplevel(widget)), GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, - _("It is not recommended to bind the primary mouse buttons without " - "modifiers.\n\n" + dialog = gtk_message_dialog_new (GTK_WINDOW(gtk_widget_get_toplevel(widget)), + GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_YES_NO, + _("It is not recommended to bind the primary mouse buttons without modifiers.\n\n" "Do you want to continue?")); gtk_window_set_title(GTK_WINDOW(dialog), _("Binding mouse buttons")); response = gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); - if (response != GTK_RESPONSE_YES) - return true; + gtk_widget_destroy (dialog); + if (response != GTK_RESPONSE_YES) return true; } controls->hotkey.key = event->button; controls->hotkey.mask = mod; - controls->hotkey.type = TYPE_MOUSE; - set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, - controls->hotkey.type); + controls->hotkey.type = TYPE_MOUSE; + Hotkey::set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); if (controls->next == nullptr) - add_callback(nullptr, (void *)controls); + add_callback (nullptr, (void *) controls); return true; } -static gboolean on_entry_scroll_event(GtkWidget * widget, - GdkEventScroll * event, void * user_data) +static gboolean +on_entry_scroll_event(GtkWidget * widget, + GdkEventScroll * event, + void * user_data) { - KeyControls * controls = (KeyControls *)user_data; - int mod; - - if (!gtk_widget_is_focus(widget)) - return false; - - mod = 0; - if (event->state & GDK_CONTROL_MASK) - mod |= ControlMask; - - if (event->state & GDK_MOD1_MASK) - mod |= Mod1Mask; + KeyControls *controls = (KeyControls*) user_data; - if (event->state & GDK_SHIFT_MASK) - mod |= ShiftMask; + if (!gtk_widget_is_focus(widget)) return false; - if (event->state & GDK_MOD5_MASK) - mod |= Mod5Mask; - - if (event->state & GDK_MOD4_MASK) - mod |= Mod4Mask; + auto mod = Hotkey::calculate_mod(event); if (event->direction == GDK_SCROLL_UP) controls->hotkey.key = 4; @@ -309,25 +192,25 @@ static gboolean on_entry_scroll_event(GtkWidget * widget, controls->hotkey.key = 6; else if (event->direction == GDK_SCROLL_RIGHT) controls->hotkey.key = 7; - else - return false; + else return false; controls->hotkey.mask = mod; - controls->hotkey.type = TYPE_MOUSE; - set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, - controls->hotkey.type); + controls->hotkey.type = TYPE_MOUSE; + Hotkey::set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); if (controls->next == nullptr) - add_callback(nullptr, (void *)controls); + add_callback (nullptr, (void *) controls); return true; } -KeyControls * add_event_controls(KeyControls * list, GtkWidget * grid, int row, - HotkeyConfiguration * hotkey) +KeyControls* add_event_controls(KeyControls* list, + GtkWidget *grid, + int row, + HotkeyConfiguration *hotkey) { - KeyControls * controls; + KeyControls *controls; int i; - controls = (KeyControls *)g_malloc(sizeof(KeyControls)); + controls = (KeyControls*) g_malloc(sizeof(KeyControls)); controls->next = nullptr; controls->prev = list; controls->first = list->first; @@ -342,119 +225,116 @@ KeyControls * add_event_controls(KeyControls * list, GtkWidget * grid, int row, controls->hotkey.event = hotkey->event; if (controls->hotkey.key == 0) controls->hotkey.mask = 0; - } - else - { + } else { controls->hotkey.key = 0; controls->hotkey.mask = 0; controls->hotkey.type = TYPE_KEY; - controls->hotkey.event = (EVENT)0; + controls->hotkey.event = (EVENT) 0; } controls->combobox = gtk_combo_box_text_new(); - for (i = 0; i < EVENT_MAX; i++) + for (i=0;icombobox, - _(event_desc[i])); + gtk_combo_box_text_append_text((GtkComboBoxText *) controls->combobox, _(event_desc[i])); } - gtk_combo_box_set_active(GTK_COMBO_BOX(controls->combobox), - controls->hotkey.event); - gtk_table_attach_defaults(GTK_TABLE(grid), controls->combobox, 0, 1, row, - row + 1); - - controls->keytext = gtk_entry_new(); - gtk_table_attach_defaults(GTK_TABLE(grid), controls->keytext, 1, 2, row, - row + 1); + gtk_combo_box_set_active(GTK_COMBO_BOX(controls->combobox), controls->hotkey.event); + gtk_table_attach_defaults (GTK_TABLE (grid), controls->combobox, 0, 1, row, row + 1); + + + controls->keytext = gtk_entry_new (); + gtk_table_attach_defaults (GTK_TABLE (grid), controls->keytext, 1, 2, row, row + 1); gtk_editable_set_editable(GTK_EDITABLE(controls->keytext), false); - set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, - controls->hotkey.type); + Hotkey::set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); g_signal_connect((void *)controls->keytext, "key_press_event", - G_CALLBACK(on_entry_key_press_event), controls); + G_CALLBACK(on_entry_key_press_event), controls); g_signal_connect((void *)controls->keytext, "key_release_event", - G_CALLBACK(on_entry_key_release_event), controls); + G_CALLBACK(on_entry_key_release_event), controls); g_signal_connect((void *)controls->keytext, "button_press_event", - G_CALLBACK(on_entry_button_press_event), controls); + G_CALLBACK(on_entry_button_press_event), controls); g_signal_connect((void *)controls->keytext, "scroll_event", - G_CALLBACK(on_entry_scroll_event), controls); + G_CALLBACK(on_entry_scroll_event), controls); + controls->button = gtk_button_new(); - gtk_button_set_image( - GTK_BUTTON(controls->button), - gtk_image_new_from_icon_name("edit-delete", GTK_ICON_SIZE_BUTTON)); - gtk_table_attach_defaults(GTK_TABLE(grid), controls->button, 2, 3, row, - row + 1); - g_signal_connect(G_OBJECT(controls->button), "clicked", - G_CALLBACK(clear_keyboard), controls); + gtk_button_set_image (GTK_BUTTON (controls->button), + gtk_image_new_from_icon_name ("edit-delete", GTK_ICON_SIZE_BUTTON)); + gtk_table_attach_defaults (GTK_TABLE (grid), controls->button, 2, 3, row, row + 1); + g_signal_connect (G_OBJECT (controls->button), "clicked", + G_CALLBACK (clear_keyboard), controls); gtk_widget_grab_focus(GTK_WIDGET(controls->keytext)); return controls; } -void * make_config_widget() +void *make_config_widget () { - KeyControls * current_controls; + KeyControls *current_controls; GtkWidget *main_vbox, *hbox; - GtkWidget * alignment; - GtkWidget * frame; - GtkWidget * label; - GtkWidget * image; - GtkWidget * grid; + GtkWidget *alignment; + GtkWidget *frame; + GtkWidget *label; + GtkWidget *image; + GtkWidget *grid; GtkWidget *button_box, *button; - PluginConfig * plugin_cfg; + PluginConfig* plugin_cfg; HotkeyConfiguration *hotkey, temphotkey; int i; - load_config(); + load_config ( ); plugin_cfg = get_config(); - ungrab_keys(); - - main_vbox = gtk_vbox_new(false, 4); - - alignment = gtk_alignment_new(0.5, 0.5, 1, 1); - gtk_box_pack_start(GTK_BOX(main_vbox), alignment, false, true, 0); - gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 4, 0, 0, 0); - hbox = gtk_hbox_new(false, 2); - gtk_container_add(GTK_CONTAINER(alignment), hbox); - image = gtk_image_new_from_icon_name("dialog-information", - GTK_ICON_SIZE_DIALOG); - gtk_box_pack_start(GTK_BOX(hbox), image, false, true, 0); - label = gtk_label_new(_("Press a key combination inside a text field.\nYou " - "can also bind mouse buttons.")); - gtk_box_pack_start(GTK_BOX(hbox), label, true, true, 0); - gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - - label = gtk_label_new(nullptr); - gtk_label_set_markup(GTK_LABEL(label), _("Hotkeys:")); - frame = gtk_frame_new(nullptr); - gtk_frame_set_label_widget(GTK_FRAME(frame), label); - gtk_box_pack_start(GTK_BOX(main_vbox), frame, true, true, 0); - gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN); - alignment = gtk_alignment_new(0, 0, 1, 0); - gtk_container_add(GTK_CONTAINER(frame), alignment); - gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 3, 3, 3, 3); - - grid = gtk_table_new(0, 0, false); - gtk_table_set_col_spacings(GTK_TABLE(grid), 2); - gtk_container_add(GTK_CONTAINER(alignment), grid); - - label = gtk_label_new(nullptr); - gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); - gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5); - gtk_label_set_markup(GTK_LABEL(label), _("Action:")); - gtk_table_attach_defaults(GTK_TABLE(grid), label, 0, 1, 0, 1); - - label = gtk_label_new(nullptr); - gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); - gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5); - gtk_label_set_markup(GTK_LABEL(label), _("Key Binding:")); - gtk_table_attach_defaults(GTK_TABLE(grid), label, 1, 2, 0, 1); + // NOTE d: implement in WIN +#ifndef _WIN32 + ungrab_keys (); +#endif + + main_vbox = gtk_vbox_new (false, 4); + + alignment = gtk_alignment_new (0.5, 0.5, 1, 1); + gtk_box_pack_start (GTK_BOX (main_vbox), alignment, false, true, 0); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 4, 0, 0, 0); + hbox = gtk_hbox_new (false, 2); + gtk_container_add (GTK_CONTAINER (alignment), hbox); + image = gtk_image_new_from_icon_name ("dialog-information", GTK_ICON_SIZE_DIALOG); + gtk_box_pack_start (GTK_BOX (hbox), image, false, true, 0); + label = gtk_label_new (_("Press a key combination inside a text field.\nYou can also bind mouse buttons.")); + gtk_box_pack_start (GTK_BOX (hbox), label, true, true, 0); + gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); + + label = gtk_label_new (nullptr); + gtk_label_set_markup (GTK_LABEL (label), _("Hotkeys:")); + frame = gtk_frame_new (nullptr); + gtk_frame_set_label_widget (GTK_FRAME (frame), label); + gtk_box_pack_start (GTK_BOX (main_vbox), frame, true, true, 0); + gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); + alignment = gtk_alignment_new (0, 0, 1, 0); + gtk_container_add (GTK_CONTAINER (frame), alignment); + gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); + + grid = gtk_table_new (0, 0, false); + gtk_table_set_col_spacings (GTK_TABLE (grid), 2); + gtk_container_add (GTK_CONTAINER (alignment), grid); + + label = gtk_label_new (nullptr); + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); + gtk_label_set_markup (GTK_LABEL (label), + _("Action:")); + gtk_table_attach_defaults (GTK_TABLE (grid), label, 0, 1, 0, 1); + + label = gtk_label_new (nullptr); + gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); + gtk_label_set_markup (GTK_LABEL (label), + _("Key Binding:")); + gtk_table_attach_defaults (GTK_TABLE (grid), label, 1, 2, 0, 1); + hotkey = &(plugin_cfg->first); i = 1; - first_controls = (KeyControls *)g_malloc(sizeof(KeyControls)); + first_controls = (KeyControls*) g_malloc(sizeof(KeyControls)); first_controls->next = nullptr; first_controls->prev = nullptr; first_controls->grid = grid; @@ -464,15 +344,14 @@ void * make_config_widget() first_controls->first = first_controls; first_controls->hotkey.key = 0; first_controls->hotkey.mask = 0; - first_controls->hotkey.event = (EVENT)0; + first_controls->hotkey.event = (EVENT) 0; first_controls->hotkey.type = TYPE_KEY; current_controls = first_controls; - if (hotkey->key != 0) + if (hotkey -> key != 0) { while (hotkey) { - current_controls = - add_event_controls(current_controls, grid, i, hotkey); + current_controls = add_event_controls(current_controls, grid, i, hotkey); hotkey = hotkey->next; i++; } @@ -481,59 +360,58 @@ void * make_config_widget() temphotkey.mask = 0; temphotkey.type = TYPE_KEY; if (current_controls != first_controls) - temphotkey.event = (EVENT)(current_controls->hotkey.event + 1); + temphotkey.event = (EVENT) (current_controls->hotkey.event + 1); else - temphotkey.event = (EVENT)0; + temphotkey.event = (EVENT) 0; if (temphotkey.event >= EVENT_MAX) - temphotkey.event = (EVENT)0; + temphotkey.event = (EVENT) 0; add_event_controls(current_controls, grid, i, &temphotkey); - hbox = gtk_hbox_new(false, 0); - gtk_box_pack_start(GTK_BOX(main_vbox), hbox, false, true, 0); - button_box = gtk_hbutton_box_new(); - gtk_box_pack_start(GTK_BOX(hbox), button_box, false, true, 0); - gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_START); - gtk_box_set_spacing(GTK_BOX(button_box), 4); + hbox = gtk_hbox_new (false, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), hbox, false, true, 0); + + button_box = gtk_hbutton_box_new (); + gtk_box_pack_start (GTK_BOX (hbox), button_box, false, true, 0); + gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_START); + gtk_box_set_spacing (GTK_BOX (button_box), 4); - button = audgui_button_new(_("_Add"), "list-add", nullptr, nullptr); - gtk_container_add(GTK_CONTAINER(button_box), button); - g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(add_callback), - first_controls); + button = audgui_button_new (_("_Add"), "list-add", nullptr, nullptr); + gtk_container_add (GTK_CONTAINER (button_box), button); + g_signal_connect (G_OBJECT (button), "clicked", + G_CALLBACK (add_callback), first_controls); return main_vbox; } -static void clear_keyboard(GtkWidget * widget, void * data) +static void clear_keyboard (GtkWidget *widget, void * data) { - KeyControls * controls = (KeyControls *)data; + KeyControls *controls= (KeyControls*)data; if ((controls->next == nullptr) && (controls->prev->keytext == nullptr)) { controls->hotkey.key = 0; controls->hotkey.mask = 0; controls->hotkey.type = TYPE_KEY; - set_keytext(controls->keytext, 0, 0, TYPE_KEY); - gtk_combo_box_set_active(GTK_COMBO_BOX(controls->combobox), 0); + Hotkey::set_keytext(controls->keytext, 0, 0, TYPE_KEY); + gtk_combo_box_set_active( GTK_COMBO_BOX(controls->combobox), 0); return; } if (controls->prev) { - KeyControls * c; - GtkWidget * grid; + KeyControls* c; + GtkWidget* grid; int row; gtk_widget_destroy(GTK_WIDGET(controls->button)); gtk_widget_destroy(GTK_WIDGET(controls->keytext)); gtk_widget_destroy(GTK_WIDGET(controls->combobox)); - row = 0; + row=0; c = controls->first; - while (c) - { - if (c == controls) - break; + while (c) { + if (c == controls) break; row++; c = c->next; } @@ -542,26 +420,20 @@ static void clear_keyboard(GtkWidget * widget, void * data) if (controls->next) controls->next->prev = controls->prev; g_free(controls); - if (c) - grid = c->grid; - else - grid = nullptr; + if (c) grid = c->grid; else grid = nullptr; while (c) { g_object_ref(c->combobox); g_object_ref(c->keytext); g_object_ref(c->button); - gtk_container_remove(GTK_CONTAINER(c->grid), c->combobox); - gtk_container_remove(GTK_CONTAINER(c->grid), c->keytext); - gtk_container_remove(GTK_CONTAINER(c->grid), c->button); + gtk_container_remove( GTK_CONTAINER(c->grid) , c->combobox); + gtk_container_remove( GTK_CONTAINER(c->grid) , c->keytext); + gtk_container_remove( GTK_CONTAINER(c->grid) , c->button); - gtk_table_attach_defaults(GTK_TABLE(c->grid), c->combobox, 0, 1, - row, row + 1); - gtk_table_attach_defaults(GTK_TABLE(c->grid), c->keytext, 1, 2, row, - row + 1); - gtk_table_attach_defaults(GTK_TABLE(c->grid), c->button, 2, 3, row, - row + 1); + gtk_table_attach_defaults (GTK_TABLE (c->grid), c->combobox, 0, 1, row, row + 1); + gtk_table_attach_defaults (GTK_TABLE (c->grid), c->keytext, 1, 2, row, row + 1); + gtk_table_attach_defaults (GTK_TABLE (c->grid), c->button, 2, 3, row, row + 1); g_object_unref(c->combobox); g_object_unref(c->keytext); @@ -571,50 +443,47 @@ static void clear_keyboard(GtkWidget * widget, void * data) row++; } if (grid) - gtk_widget_show_all(GTK_WIDGET(grid)); + gtk_widget_show_all (GTK_WIDGET (grid)); return; } } -void add_callback(GtkWidget * widget, void * data) +void add_callback (GtkWidget *widget, void * data) { - KeyControls * controls = (KeyControls *)data; + KeyControls* controls = (KeyControls*)data; HotkeyConfiguration temphotkey; int count; - if (controls == nullptr) - return; - if ((controls->next == nullptr) && - (controls->hotkey.event + 1 == EVENT_MAX)) - return; + if (controls == nullptr) return; + if ((controls->next == nullptr)&&(controls->hotkey.event+1 == EVENT_MAX)) return; controls = controls->first; - if (controls == nullptr) - return; + if (controls == nullptr) return; count = 1; - while (controls->next) - { + while (controls->next) { controls = controls->next; count = count + 1; } temphotkey.key = 0; temphotkey.mask = 0; temphotkey.type = TYPE_KEY; - temphotkey.event = (EVENT)(controls->hotkey.event + 1); + temphotkey.event = (EVENT) (controls->hotkey.event + 1); if (temphotkey.event >= EVENT_MAX) - temphotkey.event = (EVENT)0; + temphotkey.event = (EVENT) 0; add_event_controls(controls, controls->grid, count, &temphotkey); - gtk_widget_show_all(GTK_WIDGET(controls->grid)); + gtk_widget_show_all (GTK_WIDGET (controls->grid)); } -void destroy_callback() +void destroy_callback () { - KeyControls * controls = first_controls; + KeyControls* controls = first_controls; - grab_keys(); + // NOTE d: implement in WIN +#ifndef _WIN32 + grab_keys (); +#endif - while (controls) - { - KeyControls * old; + while (controls) { + KeyControls *old; old = controls; controls = controls->next; g_free(old); @@ -623,11 +492,11 @@ void destroy_callback() first_controls = nullptr; } -void ok_callback() +void ok_callback () { - KeyControls * controls = first_controls; - PluginConfig * plugin_cfg = get_config(); - HotkeyConfiguration * hotkey; + KeyControls *controls = first_controls; + PluginConfig* plugin_cfg = get_config(); + HotkeyConfiguration *hotkey; hotkey = &(plugin_cfg->first); hotkey = hotkey->next; @@ -640,36 +509,37 @@ void ok_callback() } plugin_cfg->first.next = nullptr; plugin_cfg->first.key = 0; - plugin_cfg->first.event = (EVENT)0; + plugin_cfg->first.event = (EVENT) 0; plugin_cfg->first.mask = 0; hotkey = &(plugin_cfg->first); while (controls) { - if (controls->hotkey.key) - { - if (hotkey->key) - { + if (controls->hotkey.key) { + if (hotkey->key) { hotkey->next = g_new(HotkeyConfiguration, 1); hotkey = hotkey->next; hotkey->next = nullptr; } hotkey->key = controls->hotkey.key; hotkey->mask = controls->hotkey.mask; - hotkey->event = (EVENT)gtk_combo_box_get_active( - GTK_COMBO_BOX(controls->combobox)); + hotkey->event = (EVENT) gtk_combo_box_get_active( GTK_COMBO_BOX(controls->combobox) ); hotkey->type = controls->hotkey.type; } controls = controls->next; } - save_config(); + save_config ( ); } -static const PreferencesWidget hotkey_widgets[] = { - WidgetCustomGTK(make_config_widget)}; -const PluginPreferences hotkey_prefs = {{hotkey_widgets}, - nullptr, // init - ok_callback, - destroy_callback}; +static const PreferencesWidget hotkey_widgets[] = { + WidgetCustomGTK (make_config_widget) +}; + +const PluginPreferences hotkey_prefs = { + {hotkey_widgets}, + nullptr, // init + ok_callback, + destroy_callback +}; diff --git a/src/hotkey/hotkey_api_common.cc b/src/hotkey/hotkey_api_common.cc new file mode 100644 index 0000000000..c95a017297 --- /dev/null +++ b/src/hotkey/hotkey_api_common.cc @@ -0,0 +1,103 @@ + + +#include +#include +#include +#include +#include +#include "api_hotkey.h" +#ifdef _WIN32 +#include +#include +#endif + + +template +int Hotkey::calculate_mod(T_GDK_EVENT *event) { + int mod = 0; + if (event->state & GDK_CONTROL_MASK) + mod |= HK_CONTROL_MASK; + + if (event->state & GDK_MOD1_MASK) + mod |= HK_MOD1_ALT_MASK; + + if (event->state & GDK_SHIFT_MASK) + mod |= HK_SHIFT_MASK; + + if (event->state & GDK_MOD5_MASK) + mod |= HK_MOD5_MASK; + + if (event->state & GDK_MOD4_MASK) + mod |= HK_MOD4_MASK; + return mod; +} + +template int Hotkey::calculate_mod(GdkEventScroll* event); +template int Hotkey::calculate_mod(GdkEventButton* event); +// template int Hotkey::calculate_mod(GdkEventKey* event); + +std::pair Hotkey::get_is_mod(GdkEventKey *event) { +#ifdef _WIN32 + AUDDBG("lHotkeyFlow:Win call: get_is_mod.%s", gdk_keyval_name(event->keyval)); +#endif + int mod = 0; + int is_mod = 0; + + + if ((event->state & GDK_CONTROL_MASK) + | (!is_mod && (is_mod = (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R)))) + mod |= HK_CONTROL_MASK; + + if ((event->state & GDK_MOD1_MASK) + | (!is_mod && (is_mod = (event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_R)))) + mod |= HK_MOD1_ALT_MASK; + + if ((event->state & GDK_SHIFT_MASK) + | (!is_mod && (is_mod = (event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_R)))) + mod |= HK_SHIFT_MASK; + + if ((event->state & GDK_MOD5_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_ISO_Level3_Shift)))) + mod |= HK_MOD5_MASK; + + if ((event->state & GDK_MOD4_MASK) + + | (!is_mod && (is_mod = (event->keyval == GDK_Super_L || event->keyval == GDK_Super_R)))) + mod |= HK_MOD4_MASK; + + return std::make_pair(mod, is_mod); +} + +void Hotkey::set_keytext(GtkWidget *entry, int key, int mask, int type) { + char *text = nullptr; + + if (key == 0 && mask == 0) { + text = g_strdup(_("(none)")); + } else { + static const char *modifier_string[] = {"Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5"}; + static const unsigned int modifiers[] = {HK_CONTROL_MASK, HK_SHIFT_MASK, HK_MOD1_ALT_MASK, HK_MOD2_MASK, HK_MOD3_MASK, HK_MOD4_MASK, HK_MOD5_MASK}; + const char *strings[9]; + char *keytext = nullptr; + int i, j; + if (type == TYPE_KEY) { + Hotkey::key_to_string(key, &keytext); + } + if (type == TYPE_MOUSE) { + keytext = g_strdup_printf("Button%d", key); + } + + for (i = 0, j = 0; j < 7; j++) { + if (mask & modifiers[j]) + strings[i++] = modifier_string[j]; + } + if (key != 0) strings[i++] = keytext; + strings[i] = nullptr; + + text = g_strjoinv(" + ", (char **) strings); + g_free(keytext); + } + + gtk_entry_set_text(GTK_ENTRY(entry), text); + gtk_editable_set_position(GTK_EDITABLE(entry), -1); + if (text) g_free(text); +} + diff --git a/src/hotkey/plugin.cc b/src/hotkey/plugin.cc index e1a81ebc16..dd0d77790d 100644 --- a/src/hotkey/plugin.cc +++ b/src/hotkey/plugin.cc @@ -30,16 +30,9 @@ * * You should have received a copy of the GNU General Public License * along with audacious-hotkey; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include - -#include - -#include -#include #include #include @@ -49,77 +42,96 @@ #include #include -#include "grab.h" -#include "gui.h" #include "plugin.h" +#include "gui.h" +#include "grab.h" +#include "api_hotkey.h" + +#ifdef BUILT_FROM_CMAKE +#include "../../audacious-plugins_simpleAF/src/thirdparty/d_custom_logger.hpp" +#endif class GlobalHotkeys : public GeneralPlugin { public: static const char about[]; - static constexpr PluginInfo info = {N_("Global Hotkeys"), PACKAGE, about, - &hotkey_prefs, PluginGLibOnly}; + static constexpr PluginInfo info = { + N_("Global Hotkeys"), + PACKAGE, + about, + & hotkey_prefs, + PluginGLibOnly + }; - constexpr GlobalHotkeys() : GeneralPlugin(info, false) {} + constexpr GlobalHotkeys () : GeneralPlugin (info, false) {} - bool init(); - void cleanup(); + bool init () override; + void cleanup () override; }; EXPORT GlobalHotkeys aud_plugin_instance; +#ifndef _WIN32 /* global vars */ -static PluginConfig plugin_cfg; +static +#else +PluginConfig plugin_cfg; +#endif const char GlobalHotkeys::about[] = - N_("Global Hotkey Plugin\n" - "Control the player with global key combinations or multimedia keys.\n\n" - "Copyright (C) 2007-2008 Sascha Hlusiak \n\n" - "Contributors include:\n" - "Copyright (C) 2006-2007 Vladimir Paskov \n" - "Copyright (C) 2000-2002 Ville Syrjälä ,\n" - " Bryn Davies ,\n" - " Jonathan A. Davis ,\n" - " Jeremy Tan "); - -PluginConfig * get_config() { return &plugin_cfg; } + N_("Global Hotkey Plugin\n" + "Control the player with global key combinations or multimedia keys.\n\n" + "Copyright (C) 2007-2008 Sascha Hlusiak \n\n" + "Contributors include:\n" + "Copyright (C) 2006-2007 Vladimir Paskov \n" + "Copyright (C) 2000-2002 Ville Syrjälä ,\n" + " Bryn Davies ,\n" + " Jonathan A. Davis ,\n" + " Jeremy Tan "); + +PluginConfig* get_config () +{ + return &plugin_cfg; +} /* * plugin activated */ -bool GlobalHotkeys::init() +bool GlobalHotkeys::init () { - if (!gtk_init_check(nullptr, nullptr)) +#ifdef BUILT_FROM_CMAKE + audlog::subscribe(&DCustomLogger::go, audlog::Level::Debug); +#endif + if (! gtk_init_check (nullptr, nullptr)) { - AUDERR("GTK+ initialization failed.\n"); + AUDERR ("GTK+ initialization failed.\n"); return false; } - +#ifdef _WIN32 + win_init(); +#endif setup_filter(); - load_config(); - grab_keys(); - + load_config ( ); + grab_keys (); return true; } /* handle keys */ -gboolean handle_keyevent(EVENT event) +gboolean handle_keyevent (EVENT event) { int current_volume, old_volume; static int volume_static = 0; gboolean mute; /* get current volume */ - current_volume = aud_drct_get_volume_main(); + current_volume = aud_drct_get_volume_main (); old_volume = current_volume; if (current_volume) { /* volume is not mute */ mute = false; - } - else - { + } else { /* volume is mute */ mute = true; } @@ -130,12 +142,10 @@ gboolean handle_keyevent(EVENT event) if (!mute) { volume_static = current_volume; - aud_drct_set_volume_main(0); + aud_drct_set_volume_main (0); mute = true; - } - else - { - aud_drct_set_volume_main(volume_static); + } else { + aud_drct_set_volume_main (volume_static); mute = false; } return true; @@ -151,14 +161,14 @@ gboolean handle_keyevent(EVENT event) mute = false; } - if ((current_volume -= aud_get_int("volume_delta")) < 0) + if ((current_volume -= aud_get_int ("volume_delta")) < 0) { current_volume = 0; } if (current_volume != old_volume) { - aud_drct_set_volume_main(current_volume); + aud_drct_set_volume_main (current_volume); } old_volume = current_volume; @@ -175,14 +185,14 @@ gboolean handle_keyevent(EVENT event) mute = false; } - if ((current_volume += aud_get_int("volume_delta")) > 100) + if ((current_volume += aud_get_int ("volume_delta")) > 100) { current_volume = 100; } if (current_volume != old_volume) { - aud_drct_set_volume_main(current_volume); + aud_drct_set_volume_main (current_volume); } old_volume = current_volume; @@ -192,63 +202,63 @@ gboolean handle_keyevent(EVENT event) /* play */ if (event == EVENT_PLAY) { - aud_drct_play(); + aud_drct_play (); return true; } /* pause */ if (event == EVENT_PAUSE) { - aud_drct_play_pause(); + aud_drct_play_pause (); return true; } /* stop */ if (event == EVENT_STOP) { - aud_drct_stop(); + aud_drct_stop (); return true; } /* prev track */ if (event == EVENT_PREV_TRACK) { - aud_drct_pl_prev(); + aud_drct_pl_prev (); return true; } /* next track */ if (event == EVENT_NEXT_TRACK) { - aud_drct_pl_next(); + aud_drct_pl_next (); return true; } /* forward */ if (event == EVENT_FORWARD) { - aud_drct_seek(aud_drct_get_time() + aud_get_int("step_size") * 1000); + aud_drct_seek (aud_drct_get_time () + aud_get_int ("step_size") * 1000); return true; } /* backward */ if (event == EVENT_BACKWARD) { - aud_drct_seek(aud_drct_get_time() - aud_get_int("step_size") * 1000); + aud_drct_seek (aud_drct_get_time () - aud_get_int ("step_size") * 1000); return true; } /* Open Jump-To-File dialog */ - if (event == EVENT_JUMP_TO_FILE && !aud_get_headless_mode()) + if (event == EVENT_JUMP_TO_FILE && ! aud_get_headless_mode ()) { - aud_ui_show_jump_to_song(); + aud_ui_show_jump_to_song (); return true; } /* Toggle Windows */ - if (event == EVENT_TOGGLE_WIN && !aud_get_headless_mode()) + if (event == EVENT_TOGGLE_WIN && ! aud_get_headless_mode ()) { - aud_ui_show(!aud_ui_is_shown()); + aud_ui_show (! aud_ui_is_shown ()); return true; } @@ -261,160 +271,126 @@ gboolean handle_keyevent(EVENT event) if (event == EVENT_TOGGLE_REPEAT) { - aud_toggle_bool("repeat"); + aud_toggle_bool ("repeat"); return true; } if (event == EVENT_TOGGLE_SHUFFLE) { - aud_toggle_bool("shuffle"); + aud_toggle_bool ("shuffle"); return true; } if (event == EVENT_TOGGLE_STOP) { - aud_toggle_bool("stop_after_current_song"); + aud_toggle_bool ("stop_after_current_song"); return true; } if (event == EVENT_RAISE) { - aud_ui_show(true); + aud_ui_show (true); return true; } return false; } -void add_hotkey(HotkeyConfiguration ** pphotkey, KeySym keysym, int mask, - int type, EVENT event) +void load_defaults () { - KeyCode keycode; - HotkeyConfiguration * photkey; - if (keysym == 0) - return; - if (pphotkey == nullptr) - return; - photkey = *pphotkey; - if (photkey == nullptr) - return; - keycode = XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), - keysym); - if (keycode == 0) - return; - if (photkey->key) - { - photkey->next = g_new(HotkeyConfiguration, 1); - photkey = photkey->next; - *pphotkey = photkey; - photkey->next = nullptr; - } - photkey->key = (int)keycode; - photkey->mask = mask; - photkey->event = event; - photkey->type = type; -} - -void load_defaults() -{ - HotkeyConfiguration * hotkey; + AUDDBG("lHotkeyFlow:Entry, loading defaults."); + HotkeyConfiguration* hotkey; hotkey = &(plugin_cfg.first); - add_hotkey(&hotkey, XF86XK_AudioPrev, 0, TYPE_KEY, EVENT_PREV_TRACK); - add_hotkey(&hotkey, XF86XK_AudioPlay, 0, TYPE_KEY, EVENT_PLAY); - add_hotkey(&hotkey, XF86XK_AudioPause, 0, TYPE_KEY, EVENT_PAUSE); - add_hotkey(&hotkey, XF86XK_AudioStop, 0, TYPE_KEY, EVENT_STOP); - add_hotkey(&hotkey, XF86XK_AudioNext, 0, TYPE_KEY, EVENT_NEXT_TRACK); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioPrev, 0, TYPE_KEY, EVENT_PREV_TRACK); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioPlay, 0, TYPE_KEY, EVENT_PLAY); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioPause, 0, TYPE_KEY, EVENT_PAUSE); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioStop, 0, TYPE_KEY, EVENT_STOP); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioNext, 0, TYPE_KEY, EVENT_NEXT_TRACK); - /* add_hotkey(&hotkey, XF86XK_AudioRewind, 0, TYPE_KEY, EVENT_BACKWARD); - */ +/* add_hotkey(&hotkey, OS_KEY_AudioRewind, 0, TYPE_KEY, EVENT_BACKWARD); */ - add_hotkey(&hotkey, XF86XK_AudioMute, 0, TYPE_KEY, EVENT_MUTE); - add_hotkey(&hotkey, XF86XK_AudioRaiseVolume, 0, TYPE_KEY, EVENT_VOL_UP); - add_hotkey(&hotkey, XF86XK_AudioLowerVolume, 0, TYPE_KEY, EVENT_VOL_DOWN); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioMute, 0, TYPE_KEY, EVENT_MUTE); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioRaiseVolume, 0, TYPE_KEY, EVENT_VOL_UP); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioLowerVolume, 0, TYPE_KEY, EVENT_VOL_DOWN); - /* add_hotkey(&hotkey, XF86XK_AudioMedia, 0, TYPE_KEY, - EVENT_JUMP_TO_FILE); add_hotkey(&hotkey, XF86XK_Music, 0, TYPE_KEY, - EVENT_TOGGLE_WIN); */ +/* add_hotkey(&hotkey, OS_KEY_AudioMedia, 0, TYPE_KEY, EVENT_JUMP_TO_FILE); + add_hotkey(&hotkey, XF86XK_Music, 0, TYPE_KEY, EVENT_TOGGLE_WIN); */ } /* load plugin configuration */ -void load_config() +void load_config () { - HotkeyConfiguration * hotkey; - int i, max; + HotkeyConfiguration *hotkey; + int i,max; hotkey = &(plugin_cfg.first); hotkey->next = nullptr; hotkey->key = 0; hotkey->mask = 0; - hotkey->event = (EVENT)0; + hotkey->event = (EVENT) 0; hotkey->type = TYPE_KEY; - max = aud_get_int("globalHotkey", "NumHotkeys"); + max = aud_get_int ("globalHotkey", "NumHotkeys"); if (max == 0) load_defaults(); - else - for (i = 0; i < max; i++) - { - char * text = nullptr; - - if (hotkey->key) - { - hotkey->next = g_new(HotkeyConfiguration, 1); - hotkey = hotkey->next; - hotkey->next = nullptr; - hotkey->key = 0; - hotkey->mask = 0; - hotkey->event = (EVENT)0; - hotkey->type = TYPE_KEY; - } - text = g_strdup_printf("Hotkey_%d_key", i); - hotkey->key = aud_get_int("globalHotkey", text); - g_free(text); + else for (i=0; ikey) { + hotkey->next = g_new(HotkeyConfiguration, 1); + hotkey = hotkey->next; + hotkey->next = nullptr; + hotkey->key = 0; + hotkey->mask = 0; + hotkey->event = (EVENT) 0; + hotkey->type = TYPE_KEY; + } + text = g_strdup_printf("Hotkey_%d_key", i); + hotkey->key = aud_get_int ("globalHotkey", text); + g_free(text); - text = g_strdup_printf("Hotkey_%d_mask", i); - hotkey->mask = aud_get_int("globalHotkey", text); - g_free(text); + text = g_strdup_printf("Hotkey_%d_mask", i); + hotkey->mask = aud_get_int ("globalHotkey", text); + g_free(text); - text = g_strdup_printf("Hotkey_%d_type", i); - hotkey->type = aud_get_int("globalHotkey", text); - g_free(text); + text = g_strdup_printf("Hotkey_%d_type", i); + hotkey->type = aud_get_int ("globalHotkey", text); + g_free(text); - text = g_strdup_printf("Hotkey_%d_event", i); - hotkey->event = (EVENT)aud_get_int("globalHotkey", text); - g_free(text); - } + text = g_strdup_printf("Hotkey_%d_event", i); + hotkey->event = (EVENT) aud_get_int ("globalHotkey", text); + g_free(text); + } } /* save plugin configuration */ -void save_config() +void save_config () { int max; - HotkeyConfiguration * hotkey; + HotkeyConfiguration *hotkey; hotkey = &(plugin_cfg.first); max = 0; - while (hotkey) - { - char * text = nullptr; - if (hotkey->key) - { + while (hotkey) { + char *text = nullptr; + if (hotkey->key) { text = g_strdup_printf("Hotkey_%d_key", max); - aud_set_int("globalHotkey", text, hotkey->key); + aud_set_int ("globalHotkey", text, hotkey->key); g_free(text); text = g_strdup_printf("Hotkey_%d_mask", max); - aud_set_int("globalHotkey", text, hotkey->mask); + aud_set_int ("globalHotkey", text, hotkey->mask); g_free(text); text = g_strdup_printf("Hotkey_%d_type", max); - aud_set_int("globalHotkey", text, hotkey->type); + aud_set_int ("globalHotkey", text, hotkey->type); g_free(text); text = g_strdup_printf("Hotkey_%d_event", max); - aud_set_int("globalHotkey", text, hotkey->event); + aud_set_int ("globalHotkey", text, hotkey->event); g_free(text); max++; } @@ -422,14 +398,18 @@ void save_config() hotkey = hotkey->next; } - aud_set_int("globalHotkey", "NumHotkeys", max); + aud_set_int ("globalHotkey", "NumHotkeys", max); } -void GlobalHotkeys::cleanup() +void GlobalHotkeys::cleanup () { - HotkeyConfiguration * hotkey; - ungrab_keys(); - release_filter(); +#ifdef BUILT_FROM_CMAKE + audlog::unsubscribe(&DCustomLogger::go); +#endif + + HotkeyConfiguration* hotkey; + ungrab_keys (); + release_filter(); hotkey = &(plugin_cfg.first); hotkey = hotkey->next; while (hotkey) @@ -441,6 +421,6 @@ void GlobalHotkeys::cleanup() } plugin_cfg.first.next = nullptr; plugin_cfg.first.key = 0; - plugin_cfg.first.event = (EVENT)0; + plugin_cfg.first.event = (EVENT) 0; plugin_cfg.first.mask = 0; } diff --git a/src/hotkey/plugin.h b/src/hotkey/plugin.h index d7dbbfd608..664f257b51 100644 --- a/src/hotkey/plugin.h +++ b/src/hotkey/plugin.h @@ -6,8 +6,27 @@ #define TYPE_KEY 0 #define TYPE_MOUSE 1 -typedef enum -{ +#ifdef _WIN32 +#define HK_CONTROL_MASK MOD_CONTROL +#define HK_SHIFT_MASK MOD_SHIFT +#define HK_MOD1_ALT_MASK MOD_ALT +#define HK_MOD2_MASK MOD_WIN +#define HK_MOD3_MASK 0x0016 +#define HK_MOD4_MASK 0x0032 +#define HK_MOD5_MASK 0x0064 +#define HK_WIN_NONREPEAT MOD_NOREPEAT +#else +#define HK_CONTROL_MASK ControlMask +#define HK_SHIFT_MASK ShiftMask +#define HK_MOD1_ALT_MASK Mod1Mask +#define HK_MOD2_MASK Mod2Mask +#define HK_MOD3_MASK Mod3Mask +#define HK_MOD4_MASK Mod4Mask +#define HK_MOD5_MASK Mod5Mask +#endif + + +typedef enum { EVENT_PREV_TRACK = 0, EVENT_PLAY, EVENT_PAUSE, @@ -32,23 +51,28 @@ typedef enum EVENT_MAX } EVENT; -typedef struct _HotkeyConfiguration -{ + +typedef struct _HotkeyConfiguration { unsigned key, mask; unsigned type; EVENT event; - struct _HotkeyConfiguration * next; + struct _HotkeyConfiguration *next; } HotkeyConfiguration; -typedef struct -{ +typedef struct { /* keyboard */ HotkeyConfiguration first; } PluginConfig; -void load_config(); -void save_config(); -PluginConfig * get_config(); + + +void load_config (); +void save_config (); +PluginConfig* get_config (); gboolean handle_keyevent(EVENT event); +#ifdef _WIN32 +void win_init(); +extern PluginConfig plugin_cfg; +#endif #endif diff --git a/src/hotkey/x_hotkey.cc b/src/hotkey/x_hotkey.cc new file mode 100644 index 0000000000..d668f8eaba --- /dev/null +++ b/src/hotkey/x_hotkey.cc @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +#include "api_hotkey.h" + +void Hotkey::add_hotkey(HotkeyConfiguration **pphotkey, OS_KeySym keysym, int mask, int type, EVENT event) { + KeyCode keycode; + HotkeyConfiguration *photkey; + if (keysym == 0) return; + if (pphotkey == nullptr) return; + photkey = *pphotkey; + if (photkey == nullptr) return; + keycode = XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym); + if (keycode == 0) return; + if (photkey->key) { + photkey->next = g_new(HotkeyConfiguration, 1); + photkey = photkey->next; + *pphotkey = photkey; + photkey->next = nullptr; + } + photkey->key = (int) keycode; + photkey->mask = mask; + photkey->event = event; + photkey->type = type; +} + +void Hotkey::key_to_string(int key, char **out_keytext) { + KeySym keysym; + keysym = XkbKeycodeToKeysym(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), key, 0, 0); + if (keysym == 0 || keysym == NoSymbol) { + *out_keytext = g_strdup_printf("#%d", key); + } else { + *out_keytext = g_strdup(XKeysymToString(keysym)); + } +} \ No newline at end of file diff --git a/src/hotkeyw32/Makefile b/src/hotkeyw32/Makefile new file mode 100644 index 0000000000..ef444054f3 --- /dev/null +++ b/src/hotkeyw32/Makefile @@ -0,0 +1,13 @@ +PLUGIN = hotkeyw32${PLUGIN_SUFFIX} + +SRCS = ../hotkey/gui.cc w32_grab.cc ../hotkey/grab.cc ../hotkey/plugin.cc w32_hotkey.cc ../hotkey/hotkey_api_common.cc + +include ../../buildsys.mk +include ../../extra.mk + +plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR} + +LD = ${CXX} +CFLAGS += ${PLUGIN_CFLAGS} +CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} -I../.. -I.. +LIBS += ${GLIB_LIBS} ${GTK_LIBS} -laudgui \ No newline at end of file diff --git a/src/hotkeyw32/w32_grab.cc b/src/hotkeyw32/w32_grab.cc new file mode 100644 index 0000000000..576e6c7023 --- /dev/null +++ b/src/hotkeyw32/w32_grab.cc @@ -0,0 +1,20 @@ + + + +#include "../hotkey/grab.h" + +#include + +#include +#include +#include +#include + +#include "../hotkey/plugin.h" + +void grab_keys (){ + AUDDBG("lHotkeyFlow:w_grab: grab_keys"); +} +void ungrab_keys (){ + AUDDBG("lHotkeyFlow:w_grab: ungrab_keys"); +} \ No newline at end of file diff --git a/src/hotkeyw32/w32_hotkey.cc b/src/hotkeyw32/w32_hotkey.cc new file mode 100644 index 0000000000..b3cb916391 --- /dev/null +++ b/src/hotkeyw32/w32_hotkey.cc @@ -0,0 +1,305 @@ + + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "windows_key_str_map.h" + +constexpr auto W_KEY_ID_PLAY = 18771; +constexpr auto W_KEY_ID_PREV = 18772; +constexpr auto W_KEY_ID_NEXT = 18773; +constexpr auto W_FIRST_GLOBAL_KEY_ID = 18774; + +template +std::string VirtualKeyCodeToStringMethod2(T virtualKey) { + WCHAR name[128]; + static auto key_layout = GetKeyboardLayout(0); + UINT scanCode = MapVirtualKeyEx(virtualKey, MAPVK_VK_TO_VSC, key_layout); + LONG lParamValue = (scanCode << 16); + int result = GetKeyNameTextW(lParamValue, name, 1024); + if (result > 0) { + auto *windows_cmd = reinterpret_cast(g_utf16_to_utf8( + reinterpret_cast (name), + -1, nullptr, nullptr, nullptr)); + std::string returning(windows_cmd); + g_free(windows_cmd); + return returning; + } else { + return {}; + } +} + +void Hotkey::add_hotkey(HotkeyConfiguration **pphotkey, Hotkey::OS_KeySym keysym, int mask, int type, EVENT event) { + AUDDBG("lHotkeyFlow:Win call."); + HotkeyConfiguration *photkey; + if (keysym == 0) return; + if (pphotkey == nullptr) return; + photkey = *pphotkey; + if (photkey == nullptr) return; + // keycode = XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym); + // if (keycode == 0) return; + if (photkey->key) { + photkey->next = g_new(HotkeyConfiguration, 1); + photkey = photkey->next; + *pphotkey = photkey; + photkey->next = nullptr; + } + photkey->key = (int) 42; + photkey->mask = mask; + photkey->event = event; + photkey->type = type; +} + +void register_global_keys(HWND handle){ + auto * hotkey = &(plugin_cfg.first); + auto _id = W_FIRST_GLOBAL_KEY_ID; + while (hotkey) + { + RegisterHotKey(handle, _id++, hotkey->mask, hotkey->key); + hotkey = hotkey->next; + } +} + +//void assign(wchar_t *ptr_first_element, const wchar_t *text) { +// int loc = 0; +// while (text[loc]) { +// ptr_first_element[loc] = text[loc]; +// ++loc; +// } +// ptr_first_element[loc] = 0; +//} + +HRESULT AddThumbarButtons(HWND hwnd) { + // Define an array of two buttons. These buttons provide images through an + // image list and also provide tooltips. + THUMBBUTTONMASK dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS; + + /* + THUMBBUTTONMASK dwMask; + UINT iId; + UINT iBitmap; + HICON hIcon; + WCHAR szTip[260]; + THUMBBUTTONFLAGS dwFlags; + */ + + + THUMBBUTTON btn[]{{ + dwMask, + W_KEY_ID_PREV, + 0, + nullptr, + L"Previous song", + THBF_ENABLED + }, + { + dwMask, + W_KEY_ID_PLAY, + 0, + nullptr, + L"Play/pause", + THBF_ENABLED + }, + { + dwMask, + W_KEY_ID_NEXT, + 0, + nullptr, + L"Next song", + THBF_ENABLED + } + }; + + ITaskbarList3 *ptbl; + HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&ptbl)); + + if (SUCCEEDED(hr)) { + // Declare the image list that contains the button images. + // hr = ptbl->ThumbBarSetImageList(hwnd, himl); + + if (SUCCEEDED(hr)) { + // Attach the toolbar to the thumbnail. + hr = ptbl->ThumbBarAddButtons(hwnd, ARRAYSIZE(btn), btn); + } + ptbl->Release(); + } + return hr; +} + +GdkFilterReturn buttons_evts_filter(GdkXEvent *gdk_xevent, GdkEvent *event, + gpointer user_data) { + auto msg = reinterpret_cast(gdk_xevent); + if (msg->message == WM_COMMAND) { + auto buttonId = static_cast(msg->wParam & 0xFFFF); + AUDDBG("Clicked button with ID: %d", buttonId); + switch (buttonId) { + case W_KEY_ID_PLAY:handle_keyevent(EVENT_PAUSE); + break; + case W_KEY_ID_NEXT :handle_keyevent(EVENT_NEXT_TRACK); + break; + case W_KEY_ID_PREV:handle_keyevent(EVENT_PREV_TRACK); + } + return GDK_FILTER_REMOVE; + } + if (msg->message == WM_HOTKEY) { + auto k_id = static_cast(msg->wParam & 0xFFFF); + AUDDBG("lHotkeyFlow:Global hotkey: %d" , k_id); + // Max 20 HKs + if(k_id >= W_FIRST_GLOBAL_KEY_ID && k_id < W_FIRST_GLOBAL_KEY_ID + 20){ + auto idx = k_id - W_FIRST_GLOBAL_KEY_ID; + auto * config = &plugin_cfg.first; + while(idx--){ + config = config->next; + } + handle_keyevent(config->event); + } + } + return GDK_FILTER_CONTINUE; +} + +struct EnumWindowsCallbackArgs { + explicit EnumWindowsCallbackArgs(DWORD p) : pid(p) {} + const DWORD pid; + std::vector handles; +}; + +static BOOL CALLBACK EnumWindowsCallback(HWND hnd, LPARAM lParam) { + // Get pointer to created callback object for storing data. + auto *args = reinterpret_cast ( lParam); + // Callback result are all windows (not only my program). I filter by PID / thread ID. + DWORD windowPID; + GetWindowThreadProcessId(hnd, &windowPID); + // Compare to the one we have stored in our callbaack structure. + if (windowPID == args->pid) { + args->handles.push_back(hnd); + } + + return TRUE; +} + +std::vector getToplevelWindows() { + // Create object that will hold a result. + EnumWindowsCallbackArgs args(GetCurrentProcessId()); + // AUDERR("Testing getlasterror: %ld\n.", GetLastError()); + // Call EnumWindows and pass pointer to function and created callback structure. + if (EnumWindows(&EnumWindowsCallback, (LPARAM) &args) == FALSE) { + // If the call fails, return empty vector + AUDERR("WinApiError (code %ld). Cannot get windows, hotkey plugin won't work.\n", GetLastError()); + return std::vector(); + } + // Otherwise, callback function filled the struct. Return important data. + // Test: GetActiveWindow + args.handles.push_back(GetActiveWindow()); + args.handles.push_back(GetForegroundWindow()); + return args.handles; +} + +/** + * GSourceFunc: + * @user_data: data passed to the function, set when the source was + * created with one of the above functions + * + * Specifies the type of function passed to g_timeout_add(), + * g_timeout_add_full(), g_idle_add(), and g_idle_add_full(). + * + * Returns: %FALSE if the source should be removed. #G_SOURCE_CONTINUE and + * #G_SOURCE_REMOVE are more memorable names for the return value. + */ +gboolean window_created_callback(gpointer user_data) { + + AUDDBG("lHotkeyFlow:Window created. Do real stuff."); + auto wins = getToplevelWindows(); + AUDDBG("lHotkeyFlow:windows: %zu" ,wins.size()); + for (auto win : wins) { + wchar_t className[311]; + GetClassNameW(win, className, _countof(className)); + auto s_cn = reinterpret_cast(g_utf16_to_utf8( + reinterpret_cast (className), + -1, nullptr, nullptr, nullptr)); + + GetWindowTextW(win, className, _countof(className)); + auto s_cn2 = reinterpret_cast(g_utf16_to_utf8( + reinterpret_cast (className), + -1, nullptr, nullptr, nullptr)); + if (s_cn) { + AUDDBG("lHotkeyFlow:WIN: %s%s", s_cn, ([s_cn2]() { + std::string returning{}; + if (s_cn2) { + returning = std::string(" titled: ") + s_cn2; + g_free(s_cn2); + } + return returning; + }()).c_str()); + g_free(s_cn); + } + } + auto the_hwnd = wins.back(); + // AddThumbarButtons(the_hwnd); Disabled for now ... first get hotkeys perfectly stable + auto gdkwin = gdk_win32_handle_table_lookup(the_hwnd); + gdk_window_add_filter((GdkWindow *) gdkwin, buttons_evts_filter, + nullptr); + register_global_keys(the_hwnd); + return false; +} + +void win_init() { + AUDDBG("lHotkeyFlow:Win .. important call."); + g_idle_add(&window_created_callback, + nullptr); +} + + +void Hotkey::key_to_string(int key, char **out_keytext) { + // Special handling for most OEM keys - they may depend on language or keyboard? + switch (key) { + case VK_OEM_NEC_EQUAL: + // case VK_OEM_FJ_JISHO: (note: same as EQUAL) + case VK_OEM_FJ_MASSHOU: + case VK_OEM_FJ_TOUROKU: + case VK_OEM_FJ_LOYA: + case VK_OEM_FJ_ROYA: + case VK_OEM_1: + case VK_OEM_2: + case VK_OEM_3: + case VK_OEM_4: + case VK_OEM_5: + case VK_OEM_6: + case VK_OEM_7: + case VK_OEM_8: + case VK_OEM_AX: + case VK_OEM_102: + case VK_OEM_RESET: + case VK_OEM_JUMP: + case VK_OEM_PA1: + case VK_OEM_PA2: + case VK_OEM_PA3: + case VK_OEM_WSCTRL: + case VK_OEM_CUSEL: + case VK_OEM_ATTN: + case VK_OEM_FINISH: + case VK_OEM_COPY: + case VK_OEM_AUTO: + case VK_OEM_ENLW: + case VK_OEM_BACKTAB: + case VK_OEM_CLEAR: { + auto win_str = VirtualKeyCodeToStringMethod2(key); + if (!win_str.empty()) { + *out_keytext = g_strdup(win_str.c_str()); + return; + } + } + } + *out_keytext = g_strdup(WIN_VK_NAMES[key]); +} \ No newline at end of file diff --git a/src/hotkeyw32/windows_key_str_map.h b/src/hotkeyw32/windows_key_str_map.h new file mode 100644 index 0000000000..bb40783a58 --- /dev/null +++ b/src/hotkeyw32/windows_key_str_map.h @@ -0,0 +1,266 @@ +#ifndef AUDACIOUS_PLUGINS_WINDOWS_KEY_STRINGS_HPP +#define AUDACIOUS_PLUGINS_WINDOWS_KEY_STRINGS_HPP + +// https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes +// As defined in WinUser.h + +constexpr const char *const WIN_VK_NAMES[] = { + "UNKNOWN_KEY: 0", + "LBUTTON", + "RBUTTON", + "Scroll Lock", + "MBUTTON", + "XBUTTON1", + "XBUTTON2", + "UNKNOWN_KEY: 7", + "Backspace", + "Tab", + "UNKNOWN_KEY: 10", + "UNKNOWN_KEY: 11", + "CLEAR", + "Enter", + "UNKNOWN_KEY: 14", + "UNKNOWN_KEY: 15", + "Shift", + "Ctrl", + "Alt", + "PAUSE", + "Caps Lock", + "KANA", + "UNKNOWN_KEY: 22", + "JUNJA", + "FINAL", + "HANJA", + "UNKNOWN_KEY: 26", + "Esc", + "CONVERT", + "NONCONVERT", + "ACCEPT", + "MODECHANGE", + "Space", + "Page Up", + "Page Down", + "End", + "Home", + "Left", + "Up", + "Right", + "Down", + "SELECT", + "PRINT", + "EXECUTE", + "SNAPSHOT", + "Insert", + "Delete", + "HELP", + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "UNKNOWN_KEY: 58", + "UNKNOWN_KEY: 59", + "UNKNOWN_KEY: 60", + "UNKNOWN_KEY: 61", + "UNKNOWN_KEY: 62", + "UNKNOWN_KEY: 63", + "UNKNOWN_KEY: 64", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "LWIN", + "RWIN", + "APPS", + "UNKNOWN_KEY: 94", + "SLEEP", + "Num 0", + "Num 1", + "Num 2", + "Num 3", + "Num 4", + "Num 5", + "Num 6", + "Num 7", + "Num 8", + "Num 9", + "Num *", + "Num +", + "UNKNOWN_KEY: 108", + "Num -", + "Num Del", + "Num /", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "F10", + "F11", + "F12", + "F13", + "F14", + "F15", + "F16", + "F17", + "F18", + "F19", + "F20", + "F21", + "F22", + "F23", + "F24", + "NAVIGATION_VIEW", + "NAVIGATION_MENU", + "NAVIGATION_UP", + "NAVIGATION_DOWN", + "NAVIGATION_LEFT", + "NAVIGATION_RIGHT", + "NAVIGATION_ACCEPT", + "NAVIGATION_CANCEL", + "Num Lock", + "Scroll Lock", + "OEM_NEC_EQUAL", + "OEM_FJ_MASSHOU", + "OEM_FJ_TOUROKU", + "OEM_FJ_LOYA", + "OEM_FJ_ROYA", + "UNKNOWN_KEY: 151", + "UNKNOWN_KEY: 152", + "UNKNOWN_KEY: 153", + "UNKNOWN_KEY: 154", + "UNKNOWN_KEY: 155", + "UNKNOWN_KEY: 156", + "UNKNOWN_KEY: 157", + "UNKNOWN_KEY: 158", + "UNKNOWN_KEY: 159", + "Left Shift", + "Right Shift", + "Left Ctrl", + "Right Control", + "Left Alt", + "Right Alt", + "BROWSER_BACK", + "BROWSER_FORWARD", + "BROWSER_REFRESH", + "BROWSER_STOP", + "BROWSER_SEARCH", + "BROWSER_FAVORITES", + "BROWSER_HOME", + "VOLUME_MUTE", + "VOLUME_DOWN", + "VOLUME_UP", + "MEDIA_NEXT_TRACK", + "MEDIA_PREV_TRACK", + "MEDIA_STOP", + "MEDIA_PLAY_PAUSE", + "LAUNCH_MAIL", + "LAUNCH_MEDIA_SELECT", + "LAUNCH_APP1", + "LAUNCH_APP2", + "UNKNOWN_KEY: 184", + "UNKNOWN_KEY: 185", + "OEM_1", + "OEM_PLUS", + "OEM_COMMA", + "OEM_MINUS", + "OEM_PERIOD", + "OEM_2", + "OEM_3", + "UNKNOWN_KEY: 193", + "F15", + "GAMEPAD_A", + "GAMEPAD_B", + "GAMEPAD_X", + "GAMEPAD_Y", + "GAMEPAD_RIGHT_SHOULDER", + "GAMEPAD_LEFT_SHOULDER", + "GAMEPAD_LEFT_TRIGGER", + "GAMEPAD_RIGHT_TRIGGER", + "GAMEPAD_DPAD_UP", + "GAMEPAD_DPAD_DOWN", + "GAMEPAD_DPAD_LEFT", + "GAMEPAD_DPAD_RIGHT", + "GAMEPAD_MENU", + "GAMEPAD_VIEW", + "GAMEPAD_LEFT_THUMBSTICK_BUTTON", + "GAMEPAD_RIGHT_THUMBSTICK_BUTTON", + "GAMEPAD_LEFT_THUMBSTICK_UP", + "GAMEPAD_LEFT_THUMBSTICK_DOWN", + "GAMEPAD_LEFT_THUMBSTICK_RIGHT", + "GAMEPAD_LEFT_THUMBSTICK_LEFT", + "GAMEPAD_RIGHT_THUMBSTICK_UP", + "GAMEPAD_RIGHT_THUMBSTICK_DOWN", + "GAMEPAD_RIGHT_THUMBSTICK_RIGHT", + "GAMEPAD_RIGHT_THUMBSTICK_LEFT", + "OEM_4", + "OEM_5", + "OEM_6", + "OEM_7", + "OEM_8", + "UNKNOWN_KEY: 224", + "OEM_AX", + "OEM_102", + "ICO_HELP", + "ICO_00", + "PROCESSKEY", + "ICO_CLEAR", + "PACKET", + "UNKNOWN_KEY: 232", + "OEM_RESET", + "OEM_JUMP", + "OEM_PA1", + "OEM_PA2", + "OEM_PA3", + "OEM_WSCTRL", + "OEM_CUSEL", + "OEM_ATTN", + "OEM_FINISH", + "OEM_COPY", + "OEM_AUTO", + "OEM_ENLW", + "OEM_BACKTAB", + "ATTN", + "CRSEL", + "EXSEL", + "EREOF", + "PLAY", + "ZOOM", + "NONAME", + "PA1", + "OEM_CLEAR", + "UNKNOWN_KEY: 255" +}; + +#endif //AUDACIOUS_PLUGINS_WINDOWS_KEY_STRINGS_HPP From dadc0a0648fcf547ce274503619c063a9babf03a Mon Sep 17 00:00:00 2001 From: Domen Mori Date: Sat, 29 Aug 2020 21:19:49 +0200 Subject: [PATCH 2/4] Global hotkeys clang format --- src/hotkey/api_hotkey.h | 34 +- src/hotkey/grab.cc | 407 ++++++++++++------------ src/hotkey/gui.cc | 473 +++++++++++++++------------- src/hotkey/hotkey_api_common.cc | 155 +++++---- src/hotkey/plugin.cc | 254 +++++++-------- src/hotkey/plugin.h | 21 +- src/hotkey/x_hotkey.cc | 69 ++-- src/hotkeyw32/w32_grab.cc | 9 +- src/hotkeyw32/w32_hotkey.cc | 434 +++++++++++++------------ src/hotkeyw32/windows_key_str_map.h | 7 +- 10 files changed, 975 insertions(+), 888 deletions(-) diff --git a/src/hotkey/api_hotkey.h b/src/hotkey/api_hotkey.h index 1c6e99723d..ec80d6d69b 100644 --- a/src/hotkey/api_hotkey.h +++ b/src/hotkey/api_hotkey.h @@ -9,29 +9,29 @@ #endif #include "plugin.h" +class Hotkey +{ - -class Hotkey { - -//#ifdef _WIN32 -//#define OS_KeySym int -//#else -//#define OS_KeySym KeySym -//#endif + //#ifdef _WIN32 + //#define OS_KeySym int + //#else + //#define OS_KeySym KeySym + //#endif #ifdef _WIN32 - typedef int OS_KeySym; + typedef int OS_KeySym; #else - typedef KeySym OS_KeySym; + typedef KeySym OS_KeySym; #endif - public: - static void set_keytext(GtkWidget *entry, int key, int mask, int type); - static std::pair get_is_mod(GdkEventKey *event); - template - static int calculate_mod(T_GDK_EVENT *event); - static void add_hotkey(HotkeyConfiguration **pphotkey, OS_KeySym keysym, int mask, int type, EVENT event); - static void key_to_string(int key, char **out_keytext); +public: + static void set_keytext(GtkWidget * entry, int key, int mask, int type); + static std::pair get_is_mod(GdkEventKey * event); + template + static int calculate_mod(T_GDK_EVENT * event); + static void add_hotkey(HotkeyConfiguration ** pphotkey, OS_KeySym keysym, + int mask, int type, EVENT event); + static void key_to_string(int key, char ** out_keytext); }; #ifndef _WIN32 diff --git a/src/hotkey/grab.cc b/src/hotkey/grab.cc index ffcad21bc2..1b6c7ba8ef 100644 --- a/src/hotkey/grab.cc +++ b/src/hotkey/grab.cc @@ -2,8 +2,8 @@ * This file is part of audacious-hotkey plugin for audacious * * Copyright (c) 2007 - 2008 Sascha Hlusiak - * Name: grab.c - * Description: grab.c + * Name: grab.cc + * Description: grab.cc * * Part of this code is from itouch-ctrl plugin. * Authors of itouch-ctrl are listed below: @@ -30,130 +30,39 @@ * * You should have received a copy of the GNU General Public License * along with audacious-hotkey; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ -#include - -#ifndef _WIN32 #include -#else -#include -#include -#include -#endif +#include #include "grab.h" #include "plugin.h" - static int grabbed = 0; static unsigned int numlock_mask = 0; static unsigned int scrolllock_mask = 0; static unsigned int capslock_mask = 0; - -static int x11_error_handler (Display *dpy, XErrorEvent *error) -{ - return 0; -} - -static GdkFilterReturn -gdk_filter(GdkXEvent *xevent, - GdkEvent *event, - void * data) -{ -#ifdef _WIN32 - AUDDBG("lHotkeyFlow:win CommonGrab: Filter trigger."); - assert(false); -#endif - HotkeyConfiguration *hotkey; - hotkey = &(get_config()->first); - switch (((XEvent*)xevent)->type) - { - case KeyPress: - { - XKeyEvent *keyevent = (XKeyEvent*)xevent; - while (hotkey) - { - if ((hotkey->key == keyevent->keycode) && - (hotkey->mask == (keyevent->state & ~(scrolllock_mask | numlock_mask | capslock_mask))) && - (hotkey->type == TYPE_KEY)) - { - if (handle_keyevent(hotkey->event)) - return GDK_FILTER_REMOVE; - break; - } - - hotkey = hotkey->next; - } - break; - } - case ButtonPress: - { - XButtonEvent *buttonevent = (XButtonEvent*)xevent; - while (hotkey) - { - if ((hotkey->key == buttonevent->button) && - (hotkey->mask == (buttonevent->state & ~(scrolllock_mask | numlock_mask | capslock_mask))) && - (hotkey->type == TYPE_MOUSE)) - { - if (handle_keyevent(hotkey->event)) - return GDK_FILTER_REMOVE; - break; - } - - hotkey = hotkey->next; - } - - break; - } - } - - return GDK_FILTER_CONTINUE; -} - -gboolean setup_filter() -{ -#ifdef _WIN32 - AUDDBG("lHotkeyFlow:win CommonGrab: filter up"); -#endif - gdk_window_add_filter (gdk_screen_get_root_window - (gdk_screen_get_default ()), gdk_filter, nullptr); - - return true; -} - -void release_filter() -{ -#ifdef _WIN32 - AUDDBG("lHotkeyFlow:win CommonGrab: down filter"); -#endif - gdk_window_remove_filter (gdk_screen_get_root_window - (gdk_screen_get_default ()), gdk_filter, nullptr); -} - -#ifndef _WIN32 /* Taken from xbindkeys */ -static void get_offending_modifiers (Display * dpy) +static void get_offending_modifiers(Display * dpy) { int i; - XModifierKeymap *modmap; + XModifierKeymap * modmap; KeyCode nlock, slock; - static int mask_table[8] = { - HK_SHIFT_MASK, LockMask, HK_CONTROL_MASK, HK_MOD1_ALT_MASK, - HK_MOD2_MASK, HK_MOD3_MASK, HK_MOD4_MASK, HK_MOD5_MASK - }; + static int mask_table[8] = {ShiftMask, LockMask, ControlMask, Mod1Mask, + Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask}; - nlock = XKeysymToKeycode (dpy, XK_Num_Lock); - slock = XKeysymToKeycode (dpy, XK_Scroll_Lock); + nlock = XKeysymToKeycode(dpy, XK_Num_Lock); + slock = XKeysymToKeycode(dpy, XK_Scroll_Lock); /* - * Find out the masks for the NumLock and ScrollLock modifiers, - * so that we can bind the grabs for when they are enabled too. - */ - modmap = XGetModifierMapping (dpy); + * Find out the masks for the NumLock and ScrollLock modifiers, + * so that we can bind the grabs for when they are enabled too. + */ + modmap = XGetModifierMapping(dpy); if (modmap != nullptr && modmap->max_keypermod > 0) { @@ -169,127 +78,132 @@ static void get_offending_modifiers (Display * dpy) capslock_mask = LockMask; if (modmap) - XFreeModifiermap (modmap); + XFreeModifiermap(modmap); } +static int x11_error_handler(Display * dpy, XErrorEvent * error) { return 0; } + /* grab required keys */ -static void grab_key(const HotkeyConfiguration *hotkey, Display *xdisplay, Window x_root_window) +static void grab_key(const HotkeyConfiguration * hotkey, Display * xdisplay, + Window x_root_window) { - unsigned int modifier = hotkey->mask & ~(numlock_mask | capslock_mask | scrolllock_mask); + unsigned int modifier = + hotkey->mask & ~(numlock_mask | capslock_mask | scrolllock_mask); - if (hotkey->key == 0) return; + if (hotkey->key == 0) + return; if (hotkey->type == TYPE_KEY) { - XGrabKey (xdisplay, hotkey->key, modifier, x_root_window, - False, GrabModeAsync, GrabModeAsync); + XGrabKey(xdisplay, hotkey->key, modifier, x_root_window, False, + GrabModeAsync, GrabModeAsync); if (modifier == AnyModifier) return; if (numlock_mask) - XGrabKey (xdisplay, hotkey->key, modifier | numlock_mask, - x_root_window, - False, GrabModeAsync, GrabModeAsync); + XGrabKey(xdisplay, hotkey->key, modifier | numlock_mask, + x_root_window, False, GrabModeAsync, GrabModeAsync); if (capslock_mask) - XGrabKey (xdisplay, hotkey->key, modifier | capslock_mask, - x_root_window, - False, GrabModeAsync, GrabModeAsync); + XGrabKey(xdisplay, hotkey->key, modifier | capslock_mask, + x_root_window, False, GrabModeAsync, GrabModeAsync); if (scrolllock_mask) - XGrabKey (xdisplay, hotkey->key, modifier | scrolllock_mask, - x_root_window, - False, GrabModeAsync, GrabModeAsync); + XGrabKey(xdisplay, hotkey->key, modifier | scrolllock_mask, + x_root_window, False, GrabModeAsync, GrabModeAsync); if (numlock_mask && capslock_mask) - XGrabKey (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask, - x_root_window, - False, GrabModeAsync, GrabModeAsync); + XGrabKey(xdisplay, hotkey->key, + modifier | numlock_mask | capslock_mask, x_root_window, + False, GrabModeAsync, GrabModeAsync); if (numlock_mask && scrolllock_mask) - XGrabKey (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask, - x_root_window, - False, GrabModeAsync, GrabModeAsync); + XGrabKey(xdisplay, hotkey->key, + modifier | numlock_mask | scrolllock_mask, x_root_window, + False, GrabModeAsync, GrabModeAsync); if (capslock_mask && scrolllock_mask) - XGrabKey (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask, - x_root_window, - False, GrabModeAsync, GrabModeAsync); + XGrabKey(xdisplay, hotkey->key, + modifier | capslock_mask | scrolllock_mask, x_root_window, + False, GrabModeAsync, GrabModeAsync); if (numlock_mask && capslock_mask && scrolllock_mask) - XGrabKey (xdisplay, hotkey->key, - modifier | numlock_mask | capslock_mask | scrolllock_mask, - x_root_window, False, GrabModeAsync, - GrabModeAsync); + XGrabKey(xdisplay, hotkey->key, + modifier | numlock_mask | capslock_mask | scrolllock_mask, + x_root_window, False, GrabModeAsync, GrabModeAsync); } if (hotkey->type == TYPE_MOUSE) { - XGrabButton (xdisplay, hotkey->key, modifier, x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + XGrabButton(xdisplay, hotkey->key, modifier, x_root_window, False, + ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); if (modifier == AnyModifier) return; if (numlock_mask) - XGrabButton (xdisplay, hotkey->key, modifier | numlock_mask, - x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + XGrabButton(xdisplay, hotkey->key, modifier | numlock_mask, + x_root_window, False, ButtonPressMask, GrabModeAsync, + GrabModeAsync, None, None); if (capslock_mask) - XGrabButton (xdisplay, hotkey->key, modifier | capslock_mask, - x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + XGrabButton(xdisplay, hotkey->key, modifier | capslock_mask, + x_root_window, False, ButtonPressMask, GrabModeAsync, + GrabModeAsync, None, None); if (scrolllock_mask) - XGrabButton (xdisplay, hotkey->key, modifier | scrolllock_mask, - x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + XGrabButton(xdisplay, hotkey->key, modifier | scrolllock_mask, + x_root_window, False, ButtonPressMask, GrabModeAsync, + GrabModeAsync, None, None); if (numlock_mask && capslock_mask) - XGrabButton (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask, - x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + XGrabButton(xdisplay, hotkey->key, + modifier | numlock_mask | capslock_mask, x_root_window, + False, ButtonPressMask, GrabModeAsync, GrabModeAsync, + None, None); if (numlock_mask && scrolllock_mask) - XGrabButton (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask, - x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + XGrabButton(xdisplay, hotkey->key, + modifier | numlock_mask | scrolllock_mask, + x_root_window, False, ButtonPressMask, GrabModeAsync, + GrabModeAsync, None, None); if (capslock_mask && scrolllock_mask) - XGrabButton (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask, - x_root_window, - False, ButtonPressMask, GrabModeAsync, GrabModeAsync, None, None); + XGrabButton(xdisplay, hotkey->key, + modifier | capslock_mask | scrolllock_mask, + x_root_window, False, ButtonPressMask, GrabModeAsync, + GrabModeAsync, None, None); if (numlock_mask && capslock_mask && scrolllock_mask) - XGrabButton (xdisplay, hotkey->key, - modifier | numlock_mask | capslock_mask | scrolllock_mask, - x_root_window, False, ButtonPressMask, GrabModeAsync, - GrabModeAsync, None, None); + XGrabButton(xdisplay, hotkey->key, + modifier | numlock_mask | capslock_mask | + scrolllock_mask, + x_root_window, False, ButtonPressMask, GrabModeAsync, + GrabModeAsync, None, None); } } -void grab_keys ( ) +void grab_keys() { - Display* xdisplay; + Display * xdisplay; int screen; - PluginConfig* plugin_cfg = get_config(); - HotkeyConfiguration *hotkey; + PluginConfig * plugin_cfg = get_config(); + HotkeyConfiguration * hotkey; XErrorHandler old_handler = 0; - xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); - - if (grabbed) return; + xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + if (grabbed) + return; XSync(xdisplay, False); - old_handler = XSetErrorHandler (x11_error_handler); + old_handler = XSetErrorHandler(x11_error_handler); get_offending_modifiers(xdisplay); hotkey = &(plugin_cfg->first); while (hotkey) { - for (screen=0;screenmask & ~(numlock_mask | capslock_mask | scrolllock_mask); + unsigned int modifier = + hotkey->mask & ~(numlock_mask | capslock_mask | scrolllock_mask); - if (hotkey->key == 0) return; + if (hotkey->key == 0) + return; if (hotkey->type == TYPE_KEY) { - XUngrabKey (xdisplay, hotkey->key, modifier, x_root_window); + XUngrabKey(xdisplay, hotkey->key, modifier, x_root_window); if (modifier == AnyModifier) return; if (numlock_mask) - XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask, x_root_window); + XUngrabKey(xdisplay, hotkey->key, modifier | numlock_mask, + x_root_window); if (capslock_mask) - XUngrabKey (xdisplay, hotkey->key, modifier | capslock_mask, x_root_window); + XUngrabKey(xdisplay, hotkey->key, modifier | capslock_mask, + x_root_window); if (scrolllock_mask) - XUngrabKey (xdisplay, hotkey->key, modifier | scrolllock_mask, x_root_window); + XUngrabKey(xdisplay, hotkey->key, modifier | scrolllock_mask, + x_root_window); if (numlock_mask && capslock_mask) - XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask, x_root_window); + XUngrabKey(xdisplay, hotkey->key, + modifier | numlock_mask | capslock_mask, x_root_window); if (numlock_mask && scrolllock_mask) - XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask, x_root_window); + XUngrabKey(xdisplay, hotkey->key, + modifier | numlock_mask | scrolllock_mask, + x_root_window); if (capslock_mask && scrolllock_mask) - XUngrabKey (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask, x_root_window); + XUngrabKey(xdisplay, hotkey->key, + modifier | capslock_mask | scrolllock_mask, + x_root_window); if (numlock_mask && capslock_mask && scrolllock_mask) - XUngrabKey (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window); + XUngrabKey(xdisplay, hotkey->key, + modifier | numlock_mask | capslock_mask | + scrolllock_mask, + x_root_window); } if (hotkey->type == TYPE_MOUSE) { - XUngrabButton (xdisplay, hotkey->key, modifier, x_root_window); + XUngrabButton(xdisplay, hotkey->key, modifier, x_root_window); if (modifier == AnyModifier) return; if (numlock_mask) - XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask, x_root_window); + XUngrabButton(xdisplay, hotkey->key, modifier | numlock_mask, + x_root_window); if (capslock_mask) - XUngrabButton (xdisplay, hotkey->key, modifier | capslock_mask, x_root_window); + XUngrabButton(xdisplay, hotkey->key, modifier | capslock_mask, + x_root_window); if (scrolllock_mask) - XUngrabButton (xdisplay, hotkey->key, modifier | scrolllock_mask, x_root_window); + XUngrabButton(xdisplay, hotkey->key, modifier | scrolllock_mask, + x_root_window); if (numlock_mask && capslock_mask) - XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask, x_root_window); + XUngrabButton(xdisplay, hotkey->key, + modifier | numlock_mask | capslock_mask, + x_root_window); if (numlock_mask && scrolllock_mask) - XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask | scrolllock_mask, x_root_window); + XUngrabButton(xdisplay, hotkey->key, + modifier | numlock_mask | scrolllock_mask, + x_root_window); if (capslock_mask && scrolllock_mask) - XUngrabButton (xdisplay, hotkey->key, modifier | capslock_mask | scrolllock_mask, x_root_window); + XUngrabButton(xdisplay, hotkey->key, + modifier | capslock_mask | scrolllock_mask, + x_root_window); if (numlock_mask && capslock_mask && scrolllock_mask) - XUngrabButton (xdisplay, hotkey->key, modifier | numlock_mask | capslock_mask | scrolllock_mask, x_root_window); + XUngrabButton(xdisplay, hotkey->key, + modifier | numlock_mask | capslock_mask | + scrolllock_mask, + x_root_window); } } -void ungrab_keys ( ) +void ungrab_keys() { - Display* xdisplay; + Display * xdisplay; int screen; - PluginConfig* plugin_cfg = get_config(); - HotkeyConfiguration *hotkey; + PluginConfig * plugin_cfg = get_config(); + HotkeyConfiguration * hotkey; XErrorHandler old_handler = 0; - xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); + xdisplay = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); - if (!grabbed) return; - if (!xdisplay) return; + if (!grabbed) + return; + if (!xdisplay) + return; XSync(xdisplay, False); - old_handler = XSetErrorHandler (x11_error_handler); + old_handler = XSetErrorHandler(x11_error_handler); get_offending_modifiers(xdisplay); hotkey = &(plugin_cfg->first); while (hotkey) { - for (screen=0;screenfirst); + switch (((XEvent *)xevent)->type) + { + case KeyPress: + { + XKeyEvent * keyevent = (XKeyEvent *)xevent; + while (hotkey) + { + if ((hotkey->key == keyevent->keycode) && + (hotkey->mask == + (keyevent->state & + ~(scrolllock_mask | numlock_mask | capslock_mask))) && + (hotkey->type == TYPE_KEY)) + { + if (handle_keyevent(hotkey->event)) + return GDK_FILTER_REMOVE; + break; + } + + hotkey = hotkey->next; + } + break; + } + case ButtonPress: + { + XButtonEvent * buttonevent = (XButtonEvent *)xevent; + while (hotkey) + { + if ((hotkey->key == buttonevent->button) && + (hotkey->mask == + (buttonevent->state & + ~(scrolllock_mask | numlock_mask | capslock_mask))) && + (hotkey->type == TYPE_MOUSE)) + { + if (handle_keyevent(hotkey->event)) + return GDK_FILTER_REMOVE; + break; + } + + hotkey = hotkey->next; + } + + break; + } + } + + return GDK_FILTER_CONTINUE; +} + +gboolean setup_filter() +{ + gdk_window_add_filter(gdk_screen_get_root_window(gdk_screen_get_default()), + gdk_filter, nullptr); + + return true; +} + +void release_filter() +{ + gdk_window_remove_filter( + gdk_screen_get_root_window(gdk_screen_get_default()), gdk_filter, + nullptr); +} diff --git a/src/hotkey/gui.cc b/src/hotkey/gui.cc index 454739797e..43bf977cb2 100644 --- a/src/hotkey/gui.cc +++ b/src/hotkey/gui.cc @@ -30,7 +30,8 @@ * * You should have received a copy of the GNU General Public License * along with audacious-hotkey; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include @@ -38,8 +39,8 @@ #include -#include #include +#include #include #include @@ -49,24 +50,23 @@ #include "gui.h" #include "plugin.h" -typedef struct _KeyControls { - GtkWidget *keytext; - GtkWidget *grid; - GtkWidget *button; - GtkWidget *combobox; +typedef struct _KeyControls +{ + GtkWidget * keytext; + GtkWidget * grid; + GtkWidget * button; + GtkWidget * combobox; HotkeyConfiguration hotkey; struct _KeyControls *next, *prev, *first; } KeyControls; -static KeyControls *first_controls; - - -static void clear_keyboard (GtkWidget *widget, void * data); -static void add_callback (GtkWidget *widget, void * data); -static void destroy_callback (); -static void ok_callback (); +static KeyControls * first_controls; +static void clear_keyboard(GtkWidget * widget, void * data); +static void add_callback(GtkWidget * widget, void * data); +static void destroy_callback(); +static void ok_callback(); static const char * event_desc[EVENT_MAX] = { [EVENT_PREV_TRACK] = N_("Previous track"), @@ -85,102 +85,110 @@ static const char * event_desc[EVENT_MAX] = { [EVENT_TOGGLE_REPEAT] = N_("Toggle repeat"), [EVENT_TOGGLE_SHUFFLE] = N_("Toggle shuffle"), [EVENT_TOGGLE_STOP] = N_("Toggle stop after current"), - [EVENT_RAISE] = N_("Raise player window(s)") -}; + [EVENT_RAISE] = N_("Raise player window(s)")}; -static gboolean -on_entry_key_press_event(GtkWidget * widget, - GdkEventKey * event, - void * user_data) +static gboolean on_entry_key_press_event(GtkWidget * widget, + GdkEventKey * event, void * user_data) { - AUDDBG("lHotkeyFlow:Entry"); - KeyControls *controls = (KeyControls*) user_data; + AUDDBG("lHotkeyFlow:Entry"); + KeyControls * controls = (KeyControls *)user_data; - if (event->keyval == GDK_Tab) return false; - if (event->keyval == GDK_Escape && ((event->state & ~GDK_LOCK_MASK) == 0)) return false; - if (event->keyval == GDK_Return && ((event->state & ~GDK_LOCK_MASK) == 0)) return false; + if (event->keyval == GDK_Tab) + return false; + if (event->keyval == GDK_Escape && ((event->state & ~GDK_LOCK_MASK) == 0)) + return false; + if (event->keyval == GDK_Return && ((event->state & ~GDK_LOCK_MASK) == 0)) + return false; if (event->keyval == GDK_ISO_Left_Tab) { - Hotkey::set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); + Hotkey::set_keytext(controls->keytext, controls->hotkey.key, + controls->hotkey.mask, controls->hotkey.type); return false; } - if (event->keyval == GDK_Up && ((event->state & ~GDK_LOCK_MASK) == 0)) return false; - if (event->keyval == GDK_Down && ((event->state & ~GDK_LOCK_MASK) == 0)) return false; + if (event->keyval == GDK_Up && ((event->state & ~GDK_LOCK_MASK) == 0)) + return false; + if (event->keyval == GDK_Down && ((event->state & ~GDK_LOCK_MASK) == 0)) + return false; - int mod, is_mod; - std::tie(mod, is_mod) = Hotkey::get_is_mod(event); + int mod, is_mod; + std::tie(mod, is_mod) = Hotkey::get_is_mod(event); - if (!is_mod) { - controls->hotkey.key = event->hardware_keycode; - controls->hotkey.mask = mod; - controls->hotkey.type = TYPE_KEY; - if (controls->next == nullptr) - add_callback(nullptr, (void *) controls); - else gtk_widget_grab_focus(GTK_WIDGET(controls->next->keytext)); - } + if (!is_mod) + { + controls->hotkey.key = event->hardware_keycode; + controls->hotkey.mask = mod; + controls->hotkey.type = TYPE_KEY; + if (controls->next == nullptr) + add_callback(nullptr, (void *)controls); + else + gtk_widget_grab_focus(GTK_WIDGET(controls->next->keytext)); + } - Hotkey::set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod, TYPE_KEY); - AUDDBG("lHotkeyFlow:Leave"); + Hotkey::set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, + mod, TYPE_KEY); + AUDDBG("lHotkeyFlow:Leave"); return true; } -static gboolean -on_entry_key_release_event(GtkWidget * widget, - GdkEventKey * event, - void * user_data) +static gboolean on_entry_key_release_event(GtkWidget * widget, + GdkEventKey * event, + void * user_data) { - KeyControls *controls = (KeyControls*) user_data; - if (!gtk_widget_is_focus(widget)) return false; - Hotkey::set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); + KeyControls * controls = (KeyControls *)user_data; + if (!gtk_widget_is_focus(widget)) + return false; + Hotkey::set_keytext(controls->keytext, controls->hotkey.key, + controls->hotkey.mask, controls->hotkey.type); return true; } -static gboolean -on_entry_button_press_event(GtkWidget * widget, - GdkEventButton * event, - void * user_data) +static gboolean on_entry_button_press_event(GtkWidget * widget, + GdkEventButton * event, + void * user_data) { - KeyControls *controls = (KeyControls*) user_data; + KeyControls * controls = (KeyControls *)user_data; - if (!gtk_widget_is_focus(widget)) return false; + if (!gtk_widget_is_focus(widget)) + return false; - int mod = Hotkey::calculate_mod(event); + int mod = Hotkey::calculate_mod(event); if ((event->button <= 3) && (mod == 0)) { - GtkWidget* dialog; + GtkWidget * dialog; int response; - dialog = gtk_message_dialog_new (GTK_WINDOW(gtk_widget_get_toplevel(widget)), - GTK_DIALOG_MODAL, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_YES_NO, - _("It is not recommended to bind the primary mouse buttons without modifiers.\n\n" + dialog = gtk_message_dialog_new( + GTK_WINDOW(gtk_widget_get_toplevel(widget)), GTK_DIALOG_MODAL, + GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, + _("It is not recommended to bind the primary mouse buttons without " + "modifiers.\n\n" "Do you want to continue?")); gtk_window_set_title(GTK_WINDOW(dialog), _("Binding mouse buttons")); response = gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy (dialog); - if (response != GTK_RESPONSE_YES) return true; + gtk_widget_destroy(dialog); + if (response != GTK_RESPONSE_YES) + return true; } controls->hotkey.key = event->button; controls->hotkey.mask = mod; - controls->hotkey.type = TYPE_MOUSE; - Hotkey::set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); + controls->hotkey.type = TYPE_MOUSE; + Hotkey::set_keytext(controls->keytext, controls->hotkey.key, + controls->hotkey.mask, controls->hotkey.type); if (controls->next == nullptr) - add_callback (nullptr, (void *) controls); + add_callback(nullptr, (void *)controls); return true; } -static gboolean -on_entry_scroll_event(GtkWidget * widget, - GdkEventScroll * event, - void * user_data) +static gboolean on_entry_scroll_event(GtkWidget * widget, + GdkEventScroll * event, void * user_data) { - KeyControls *controls = (KeyControls*) user_data; + KeyControls * controls = (KeyControls *)user_data; - if (!gtk_widget_is_focus(widget)) return false; + if (!gtk_widget_is_focus(widget)) + return false; auto mod = Hotkey::calculate_mod(event); @@ -192,25 +200,25 @@ on_entry_scroll_event(GtkWidget * widget, controls->hotkey.key = 6; else if (event->direction == GDK_SCROLL_RIGHT) controls->hotkey.key = 7; - else return false; + else + return false; controls->hotkey.mask = mod; - controls->hotkey.type = TYPE_MOUSE; - Hotkey::set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); + controls->hotkey.type = TYPE_MOUSE; + Hotkey::set_keytext(controls->keytext, controls->hotkey.key, + controls->hotkey.mask, controls->hotkey.type); if (controls->next == nullptr) - add_callback (nullptr, (void *) controls); + add_callback(nullptr, (void *)controls); return true; } -KeyControls* add_event_controls(KeyControls* list, - GtkWidget *grid, - int row, - HotkeyConfiguration *hotkey) +KeyControls * add_event_controls(KeyControls * list, GtkWidget * grid, int row, + HotkeyConfiguration * hotkey) { - KeyControls *controls; + KeyControls * controls; int i; - controls = (KeyControls*) g_malloc(sizeof(KeyControls)); + controls = (KeyControls *)g_malloc(sizeof(KeyControls)); controls->next = nullptr; controls->prev = list; controls->first = list->first; @@ -225,116 +233,122 @@ KeyControls* add_event_controls(KeyControls* list, controls->hotkey.event = hotkey->event; if (controls->hotkey.key == 0) controls->hotkey.mask = 0; - } else { + } + else + { controls->hotkey.key = 0; controls->hotkey.mask = 0; controls->hotkey.type = TYPE_KEY; - controls->hotkey.event = (EVENT) 0; + controls->hotkey.event = (EVENT)0; } controls->combobox = gtk_combo_box_text_new(); - for (i=0;icombobox, _(event_desc[i])); + gtk_combo_box_text_append_text((GtkComboBoxText *)controls->combobox, + _(event_desc[i])); } - gtk_combo_box_set_active(GTK_COMBO_BOX(controls->combobox), controls->hotkey.event); - gtk_table_attach_defaults (GTK_TABLE (grid), controls->combobox, 0, 1, row, row + 1); - - - controls->keytext = gtk_entry_new (); - gtk_table_attach_defaults (GTK_TABLE (grid), controls->keytext, 1, 2, row, row + 1); + gtk_combo_box_set_active(GTK_COMBO_BOX(controls->combobox), + controls->hotkey.event); + gtk_table_attach_defaults(GTK_TABLE(grid), controls->combobox, 0, 1, row, + row + 1); + + controls->keytext = gtk_entry_new(); + gtk_table_attach_defaults(GTK_TABLE(grid), controls->keytext, 1, 2, row, + row + 1); gtk_editable_set_editable(GTK_EDITABLE(controls->keytext), false); - Hotkey::set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); + Hotkey::set_keytext(controls->keytext, controls->hotkey.key, + controls->hotkey.mask, controls->hotkey.type); g_signal_connect((void *)controls->keytext, "key_press_event", - G_CALLBACK(on_entry_key_press_event), controls); + G_CALLBACK(on_entry_key_press_event), controls); g_signal_connect((void *)controls->keytext, "key_release_event", - G_CALLBACK(on_entry_key_release_event), controls); + G_CALLBACK(on_entry_key_release_event), controls); g_signal_connect((void *)controls->keytext, "button_press_event", - G_CALLBACK(on_entry_button_press_event), controls); + G_CALLBACK(on_entry_button_press_event), controls); g_signal_connect((void *)controls->keytext, "scroll_event", - G_CALLBACK(on_entry_scroll_event), controls); - + G_CALLBACK(on_entry_scroll_event), controls); controls->button = gtk_button_new(); - gtk_button_set_image (GTK_BUTTON (controls->button), - gtk_image_new_from_icon_name ("edit-delete", GTK_ICON_SIZE_BUTTON)); - gtk_table_attach_defaults (GTK_TABLE (grid), controls->button, 2, 3, row, row + 1); - g_signal_connect (G_OBJECT (controls->button), "clicked", - G_CALLBACK (clear_keyboard), controls); + gtk_button_set_image( + GTK_BUTTON(controls->button), + gtk_image_new_from_icon_name("edit-delete", GTK_ICON_SIZE_BUTTON)); + gtk_table_attach_defaults(GTK_TABLE(grid), controls->button, 2, 3, row, + row + 1); + g_signal_connect(G_OBJECT(controls->button), "clicked", + G_CALLBACK(clear_keyboard), controls); gtk_widget_grab_focus(GTK_WIDGET(controls->keytext)); return controls; } -void *make_config_widget () +void * make_config_widget() { - KeyControls *current_controls; + KeyControls * current_controls; GtkWidget *main_vbox, *hbox; - GtkWidget *alignment; - GtkWidget *frame; - GtkWidget *label; - GtkWidget *image; - GtkWidget *grid; + GtkWidget * alignment; + GtkWidget * frame; + GtkWidget * label; + GtkWidget * image; + GtkWidget * grid; GtkWidget *button_box, *button; - PluginConfig* plugin_cfg; + PluginConfig * plugin_cfg; HotkeyConfiguration *hotkey, temphotkey; int i; - load_config ( ); + load_config(); plugin_cfg = get_config(); - // NOTE d: implement in WIN + // NOTE d: implement in WIN #ifndef _WIN32 - ungrab_keys (); + ungrab_keys(); #endif - main_vbox = gtk_vbox_new (false, 4); - - alignment = gtk_alignment_new (0.5, 0.5, 1, 1); - gtk_box_pack_start (GTK_BOX (main_vbox), alignment, false, true, 0); - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 4, 0, 0, 0); - hbox = gtk_hbox_new (false, 2); - gtk_container_add (GTK_CONTAINER (alignment), hbox); - image = gtk_image_new_from_icon_name ("dialog-information", GTK_ICON_SIZE_DIALOG); - gtk_box_pack_start (GTK_BOX (hbox), image, false, true, 0); - label = gtk_label_new (_("Press a key combination inside a text field.\nYou can also bind mouse buttons.")); - gtk_box_pack_start (GTK_BOX (hbox), label, true, true, 0); - gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); - - label = gtk_label_new (nullptr); - gtk_label_set_markup (GTK_LABEL (label), _("Hotkeys:")); - frame = gtk_frame_new (nullptr); - gtk_frame_set_label_widget (GTK_FRAME (frame), label); - gtk_box_pack_start (GTK_BOX (main_vbox), frame, true, true, 0); - gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); - alignment = gtk_alignment_new (0, 0, 1, 0); - gtk_container_add (GTK_CONTAINER (frame), alignment); - gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); - - grid = gtk_table_new (0, 0, false); - gtk_table_set_col_spacings (GTK_TABLE (grid), 2); - gtk_container_add (GTK_CONTAINER (alignment), grid); - - label = gtk_label_new (nullptr); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - gtk_label_set_markup (GTK_LABEL (label), - _("Action:")); - gtk_table_attach_defaults (GTK_TABLE (grid), label, 0, 1, 0, 1); - - label = gtk_label_new (nullptr); - gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_CENTER); - gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5); - gtk_label_set_markup (GTK_LABEL (label), - _("Key Binding:")); - gtk_table_attach_defaults (GTK_TABLE (grid), label, 1, 2, 0, 1); - + main_vbox = gtk_vbox_new(false, 4); + + alignment = gtk_alignment_new(0.5, 0.5, 1, 1); + gtk_box_pack_start(GTK_BOX(main_vbox), alignment, false, true, 0); + gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 4, 0, 0, 0); + hbox = gtk_hbox_new(false, 2); + gtk_container_add(GTK_CONTAINER(alignment), hbox); + image = gtk_image_new_from_icon_name("dialog-information", + GTK_ICON_SIZE_DIALOG); + gtk_box_pack_start(GTK_BOX(hbox), image, false, true, 0); + label = gtk_label_new(_("Press a key combination inside a text field.\nYou " + "can also bind mouse buttons.")); + gtk_box_pack_start(GTK_BOX(hbox), label, true, true, 0); + gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + + label = gtk_label_new(nullptr); + gtk_label_set_markup(GTK_LABEL(label), _("Hotkeys:")); + frame = gtk_frame_new(nullptr); + gtk_frame_set_label_widget(GTK_FRAME(frame), label); + gtk_box_pack_start(GTK_BOX(main_vbox), frame, true, true, 0); + gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN); + alignment = gtk_alignment_new(0, 0, 1, 0); + gtk_container_add(GTK_CONTAINER(frame), alignment); + gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 3, 3, 3, 3); + + grid = gtk_table_new(0, 0, false); + gtk_table_set_col_spacings(GTK_TABLE(grid), 2); + gtk_container_add(GTK_CONTAINER(alignment), grid); + + label = gtk_label_new(nullptr); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5); + gtk_label_set_markup(GTK_LABEL(label), _("Action:")); + gtk_table_attach_defaults(GTK_TABLE(grid), label, 0, 1, 0, 1); + + label = gtk_label_new(nullptr); + gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5); + gtk_label_set_markup(GTK_LABEL(label), _("Key Binding:")); + gtk_table_attach_defaults(GTK_TABLE(grid), label, 1, 2, 0, 1); hotkey = &(plugin_cfg->first); i = 1; - first_controls = (KeyControls*) g_malloc(sizeof(KeyControls)); + first_controls = (KeyControls *)g_malloc(sizeof(KeyControls)); first_controls->next = nullptr; first_controls->prev = nullptr; first_controls->grid = grid; @@ -344,14 +358,15 @@ void *make_config_widget () first_controls->first = first_controls; first_controls->hotkey.key = 0; first_controls->hotkey.mask = 0; - first_controls->hotkey.event = (EVENT) 0; + first_controls->hotkey.event = (EVENT)0; first_controls->hotkey.type = TYPE_KEY; current_controls = first_controls; - if (hotkey -> key != 0) + if (hotkey->key != 0) { while (hotkey) { - current_controls = add_event_controls(current_controls, grid, i, hotkey); + current_controls = + add_event_controls(current_controls, grid, i, hotkey); hotkey = hotkey->next; i++; } @@ -360,58 +375,59 @@ void *make_config_widget () temphotkey.mask = 0; temphotkey.type = TYPE_KEY; if (current_controls != first_controls) - temphotkey.event = (EVENT) (current_controls->hotkey.event + 1); + temphotkey.event = (EVENT)(current_controls->hotkey.event + 1); else - temphotkey.event = (EVENT) 0; + temphotkey.event = (EVENT)0; if (temphotkey.event >= EVENT_MAX) - temphotkey.event = (EVENT) 0; + temphotkey.event = (EVENT)0; add_event_controls(current_controls, grid, i, &temphotkey); + hbox = gtk_hbox_new(false, 0); + gtk_box_pack_start(GTK_BOX(main_vbox), hbox, false, true, 0); - hbox = gtk_hbox_new (false, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), hbox, false, true, 0); - - button_box = gtk_hbutton_box_new (); - gtk_box_pack_start (GTK_BOX (hbox), button_box, false, true, 0); - gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_START); - gtk_box_set_spacing (GTK_BOX (button_box), 4); + button_box = gtk_hbutton_box_new(); + gtk_box_pack_start(GTK_BOX(hbox), button_box, false, true, 0); + gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_START); + gtk_box_set_spacing(GTK_BOX(button_box), 4); - button = audgui_button_new (_("_Add"), "list-add", nullptr, nullptr); - gtk_container_add (GTK_CONTAINER (button_box), button); - g_signal_connect (G_OBJECT (button), "clicked", - G_CALLBACK (add_callback), first_controls); + button = audgui_button_new(_("_Add"), "list-add", nullptr, nullptr); + gtk_container_add(GTK_CONTAINER(button_box), button); + g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(add_callback), + first_controls); return main_vbox; } -static void clear_keyboard (GtkWidget *widget, void * data) +static void clear_keyboard(GtkWidget * widget, void * data) { - KeyControls *controls= (KeyControls*)data; + KeyControls * controls = (KeyControls *)data; if ((controls->next == nullptr) && (controls->prev->keytext == nullptr)) { controls->hotkey.key = 0; controls->hotkey.mask = 0; controls->hotkey.type = TYPE_KEY; - Hotkey::set_keytext(controls->keytext, 0, 0, TYPE_KEY); - gtk_combo_box_set_active( GTK_COMBO_BOX(controls->combobox), 0); + Hotkey::set_keytext(controls->keytext, 0, 0, TYPE_KEY); + gtk_combo_box_set_active(GTK_COMBO_BOX(controls->combobox), 0); return; } if (controls->prev) { - KeyControls* c; - GtkWidget* grid; + KeyControls * c; + GtkWidget * grid; int row; gtk_widget_destroy(GTK_WIDGET(controls->button)); gtk_widget_destroy(GTK_WIDGET(controls->keytext)); gtk_widget_destroy(GTK_WIDGET(controls->combobox)); - row=0; + row = 0; c = controls->first; - while (c) { - if (c == controls) break; + while (c) + { + if (c == controls) + break; row++; c = c->next; } @@ -420,20 +436,26 @@ static void clear_keyboard (GtkWidget *widget, void * data) if (controls->next) controls->next->prev = controls->prev; g_free(controls); - if (c) grid = c->grid; else grid = nullptr; + if (c) + grid = c->grid; + else + grid = nullptr; while (c) { g_object_ref(c->combobox); g_object_ref(c->keytext); g_object_ref(c->button); - gtk_container_remove( GTK_CONTAINER(c->grid) , c->combobox); - gtk_container_remove( GTK_CONTAINER(c->grid) , c->keytext); - gtk_container_remove( GTK_CONTAINER(c->grid) , c->button); + gtk_container_remove(GTK_CONTAINER(c->grid), c->combobox); + gtk_container_remove(GTK_CONTAINER(c->grid), c->keytext); + gtk_container_remove(GTK_CONTAINER(c->grid), c->button); - gtk_table_attach_defaults (GTK_TABLE (c->grid), c->combobox, 0, 1, row, row + 1); - gtk_table_attach_defaults (GTK_TABLE (c->grid), c->keytext, 1, 2, row, row + 1); - gtk_table_attach_defaults (GTK_TABLE (c->grid), c->button, 2, 3, row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(c->grid), c->combobox, 0, 1, + row, row + 1); + gtk_table_attach_defaults(GTK_TABLE(c->grid), c->keytext, 1, 2, row, + row + 1); + gtk_table_attach_defaults(GTK_TABLE(c->grid), c->button, 2, 3, row, + row + 1); g_object_unref(c->combobox); g_object_unref(c->keytext); @@ -443,47 +465,53 @@ static void clear_keyboard (GtkWidget *widget, void * data) row++; } if (grid) - gtk_widget_show_all (GTK_WIDGET (grid)); + gtk_widget_show_all(GTK_WIDGET(grid)); return; } } -void add_callback (GtkWidget *widget, void * data) +void add_callback(GtkWidget * widget, void * data) { - KeyControls* controls = (KeyControls*)data; + KeyControls * controls = (KeyControls *)data; HotkeyConfiguration temphotkey; int count; - if (controls == nullptr) return; - if ((controls->next == nullptr)&&(controls->hotkey.event+1 == EVENT_MAX)) return; + if (controls == nullptr) + return; + if ((controls->next == nullptr) && + (controls->hotkey.event + 1 == EVENT_MAX)) + return; controls = controls->first; - if (controls == nullptr) return; + if (controls == nullptr) + return; count = 1; - while (controls->next) { + while (controls->next) + { controls = controls->next; count = count + 1; } temphotkey.key = 0; temphotkey.mask = 0; temphotkey.type = TYPE_KEY; - temphotkey.event = (EVENT) (controls->hotkey.event + 1); + temphotkey.event = (EVENT)(controls->hotkey.event + 1); if (temphotkey.event >= EVENT_MAX) - temphotkey.event = (EVENT) 0; + temphotkey.event = (EVENT)0; add_event_controls(controls, controls->grid, count, &temphotkey); - gtk_widget_show_all (GTK_WIDGET (controls->grid)); + gtk_widget_show_all(GTK_WIDGET(controls->grid)); } -void destroy_callback () +void destroy_callback() { - KeyControls* controls = first_controls; + KeyControls * controls = first_controls; - // NOTE d: implement in WIN + // NOTE d: implement in WIN #ifndef _WIN32 - grab_keys (); + grab_keys(); #endif - while (controls) { - KeyControls *old; + while (controls) + { + KeyControls * old; old = controls; controls = controls->next; g_free(old); @@ -492,11 +520,11 @@ void destroy_callback () first_controls = nullptr; } -void ok_callback () +void ok_callback() { - KeyControls *controls = first_controls; - PluginConfig* plugin_cfg = get_config(); - HotkeyConfiguration *hotkey; + KeyControls * controls = first_controls; + PluginConfig * plugin_cfg = get_config(); + HotkeyConfiguration * hotkey; hotkey = &(plugin_cfg->first); hotkey = hotkey->next; @@ -509,37 +537,36 @@ void ok_callback () } plugin_cfg->first.next = nullptr; plugin_cfg->first.key = 0; - plugin_cfg->first.event = (EVENT) 0; + plugin_cfg->first.event = (EVENT)0; plugin_cfg->first.mask = 0; hotkey = &(plugin_cfg->first); while (controls) { - if (controls->hotkey.key) { - if (hotkey->key) { + if (controls->hotkey.key) + { + if (hotkey->key) + { hotkey->next = g_new(HotkeyConfiguration, 1); hotkey = hotkey->next; hotkey->next = nullptr; } hotkey->key = controls->hotkey.key; hotkey->mask = controls->hotkey.mask; - hotkey->event = (EVENT) gtk_combo_box_get_active( GTK_COMBO_BOX(controls->combobox) ); + hotkey->event = (EVENT)gtk_combo_box_get_active( + GTK_COMBO_BOX(controls->combobox)); hotkey->type = controls->hotkey.type; } controls = controls->next; } - save_config ( ); + save_config(); } - static const PreferencesWidget hotkey_widgets[] = { - WidgetCustomGTK (make_config_widget) -}; - -const PluginPreferences hotkey_prefs = { - {hotkey_widgets}, - nullptr, // init - ok_callback, - destroy_callback -}; + WidgetCustomGTK(make_config_widget)}; + +const PluginPreferences hotkey_prefs = {{hotkey_widgets}, + nullptr, // init + ok_callback, + destroy_callback}; diff --git a/src/hotkey/hotkey_api_common.cc b/src/hotkey/hotkey_api_common.cc index c95a017297..eb59c912c8 100644 --- a/src/hotkey/hotkey_api_common.cc +++ b/src/hotkey/hotkey_api_common.cc @@ -1,103 +1,120 @@ +#include "api_hotkey.h" +#include #include #include -#include -#include #include -#include "api_hotkey.h" +#include #ifdef _WIN32 #include #include #endif - template -int Hotkey::calculate_mod(T_GDK_EVENT *event) { - int mod = 0; - if (event->state & GDK_CONTROL_MASK) - mod |= HK_CONTROL_MASK; +int Hotkey::calculate_mod(T_GDK_EVENT * event) +{ + int mod = 0; + if (event->state & GDK_CONTROL_MASK) + mod |= HK_CONTROL_MASK; - if (event->state & GDK_MOD1_MASK) - mod |= HK_MOD1_ALT_MASK; + if (event->state & GDK_MOD1_MASK) + mod |= HK_MOD1_ALT_MASK; - if (event->state & GDK_SHIFT_MASK) - mod |= HK_SHIFT_MASK; + if (event->state & GDK_SHIFT_MASK) + mod |= HK_SHIFT_MASK; - if (event->state & GDK_MOD5_MASK) - mod |= HK_MOD5_MASK; + if (event->state & GDK_MOD5_MASK) + mod |= HK_MOD5_MASK; - if (event->state & GDK_MOD4_MASK) - mod |= HK_MOD4_MASK; - return mod; + if (event->state & GDK_MOD4_MASK) + mod |= HK_MOD4_MASK; + return mod; } -template int Hotkey::calculate_mod(GdkEventScroll* event); -template int Hotkey::calculate_mod(GdkEventButton* event); +template int Hotkey::calculate_mod(GdkEventScroll * event); +template int Hotkey::calculate_mod(GdkEventButton * event); // template int Hotkey::calculate_mod(GdkEventKey* event); -std::pair Hotkey::get_is_mod(GdkEventKey *event) { +std::pair Hotkey::get_is_mod(GdkEventKey * event) +{ #ifdef _WIN32 - AUDDBG("lHotkeyFlow:Win call: get_is_mod.%s", gdk_keyval_name(event->keyval)); + AUDDBG("lHotkeyFlow:Win call: get_is_mod.%s", + gdk_keyval_name(event->keyval)); #endif - int mod = 0; - int is_mod = 0; + int mod = 0; + int is_mod = 0; + if ((event->state & GDK_CONTROL_MASK) | + (!is_mod && (is_mod = (event->keyval == GDK_Control_L || + event->keyval == GDK_Control_R)))) + mod |= HK_CONTROL_MASK; - if ((event->state & GDK_CONTROL_MASK) - | (!is_mod && (is_mod = (event->keyval == GDK_Control_L || event->keyval == GDK_Control_R)))) - mod |= HK_CONTROL_MASK; + if ((event->state & GDK_MOD1_MASK) | + (!is_mod && + (is_mod = (event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_R)))) + mod |= HK_MOD1_ALT_MASK; - if ((event->state & GDK_MOD1_MASK) - | (!is_mod && (is_mod = (event->keyval == GDK_Alt_L || event->keyval == GDK_Alt_R)))) - mod |= HK_MOD1_ALT_MASK; + if ((event->state & GDK_SHIFT_MASK) | + (!is_mod && (is_mod = (event->keyval == GDK_Shift_L || + event->keyval == GDK_Shift_R)))) + mod |= HK_SHIFT_MASK; - if ((event->state & GDK_SHIFT_MASK) - | (!is_mod && (is_mod = (event->keyval == GDK_Shift_L || event->keyval == GDK_Shift_R)))) - mod |= HK_SHIFT_MASK; + if ((event->state & GDK_MOD5_MASK) | + (!is_mod && (is_mod = (event->keyval == GDK_ISO_Level3_Shift)))) + mod |= HK_MOD5_MASK; - if ((event->state & GDK_MOD5_MASK) | (!is_mod && (is_mod = (event->keyval == GDK_ISO_Level3_Shift)))) - mod |= HK_MOD5_MASK; + if ((event->state & GDK_MOD4_MASK) - if ((event->state & GDK_MOD4_MASK) + | (!is_mod && (is_mod = (event->keyval == GDK_Super_L || + event->keyval == GDK_Super_R)))) + mod |= HK_MOD4_MASK; - | (!is_mod && (is_mod = (event->keyval == GDK_Super_L || event->keyval == GDK_Super_R)))) - mod |= HK_MOD4_MASK; - - return std::make_pair(mod, is_mod); + return std::make_pair(mod, is_mod); } -void Hotkey::set_keytext(GtkWidget *entry, int key, int mask, int type) { - char *text = nullptr; - - if (key == 0 && mask == 0) { - text = g_strdup(_("(none)")); - } else { - static const char *modifier_string[] = {"Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5"}; - static const unsigned int modifiers[] = {HK_CONTROL_MASK, HK_SHIFT_MASK, HK_MOD1_ALT_MASK, HK_MOD2_MASK, HK_MOD3_MASK, HK_MOD4_MASK, HK_MOD5_MASK}; - const char *strings[9]; - char *keytext = nullptr; - int i, j; - if (type == TYPE_KEY) { - Hotkey::key_to_string(key, &keytext); - } - if (type == TYPE_MOUSE) { - keytext = g_strdup_printf("Button%d", key); - } +void Hotkey::set_keytext(GtkWidget * entry, int key, int mask, int type) +{ + char * text = nullptr; - for (i = 0, j = 0; j < 7; j++) { - if (mask & modifiers[j]) - strings[i++] = modifier_string[j]; + if (key == 0 && mask == 0) + { + text = g_strdup(_("(none)")); + } + else + { + static const char * modifier_string[] = { + "Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5"}; + static const unsigned int modifiers[] = { + HK_CONTROL_MASK, HK_SHIFT_MASK, HK_MOD1_ALT_MASK, HK_MOD2_MASK, + HK_MOD3_MASK, HK_MOD4_MASK, HK_MOD5_MASK}; + const char * strings[9]; + char * keytext = nullptr; + int i, j; + if (type == TYPE_KEY) + { + Hotkey::key_to_string(key, &keytext); + } + if (type == TYPE_MOUSE) + { + keytext = g_strdup_printf("Button%d", key); + } + + for (i = 0, j = 0; j < 7; j++) + { + if (mask & modifiers[j]) + strings[i++] = modifier_string[j]; + } + if (key != 0) + strings[i++] = keytext; + strings[i] = nullptr; + + text = g_strjoinv(" + ", (char **)strings); + g_free(keytext); } - if (key != 0) strings[i++] = keytext; - strings[i] = nullptr; - - text = g_strjoinv(" + ", (char **) strings); - g_free(keytext); - } - gtk_entry_set_text(GTK_ENTRY(entry), text); - gtk_editable_set_position(GTK_EDITABLE(entry), -1); - if (text) g_free(text); + gtk_entry_set_text(GTK_ENTRY(entry), text); + gtk_editable_set_position(GTK_EDITABLE(entry), -1); + if (text) + g_free(text); } - diff --git a/src/hotkey/plugin.cc b/src/hotkey/plugin.cc index dd0d77790d..6b05267b6f 100644 --- a/src/hotkey/plugin.cc +++ b/src/hotkey/plugin.cc @@ -30,7 +30,8 @@ * * You should have received a copy of the GNU General Public License * along with audacious-hotkey; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. */ #include @@ -42,10 +43,10 @@ #include #include -#include "plugin.h" -#include "gui.h" -#include "grab.h" #include "api_hotkey.h" +#include "grab.h" +#include "gui.h" +#include "plugin.h" #ifdef BUILT_FROM_CMAKE #include "../../audacious-plugins_simpleAF/src/thirdparty/d_custom_logger.hpp" @@ -56,18 +57,13 @@ class GlobalHotkeys : public GeneralPlugin public: static const char about[]; - static constexpr PluginInfo info = { - N_("Global Hotkeys"), - PACKAGE, - about, - & hotkey_prefs, - PluginGLibOnly - }; + static constexpr PluginInfo info = {N_("Global Hotkeys"), PACKAGE, about, + &hotkey_prefs, PluginGLibOnly}; - constexpr GlobalHotkeys () : GeneralPlugin (info, false) {} + constexpr GlobalHotkeys() : GeneralPlugin(info, false) {} - bool init () override; - void cleanup () override; + bool init() override; + void cleanup() override; }; EXPORT GlobalHotkeys aud_plugin_instance; @@ -79,59 +75,59 @@ static PluginConfig plugin_cfg; #endif -const char GlobalHotkeys::about[] = - N_("Global Hotkey Plugin\n" - "Control the player with global key combinations or multimedia keys.\n\n" - "Copyright (C) 2007-2008 Sascha Hlusiak \n\n" - "Contributors include:\n" - "Copyright (C) 2006-2007 Vladimir Paskov \n" - "Copyright (C) 2000-2002 Ville Syrjälä ,\n" - " Bryn Davies ,\n" - " Jonathan A. Davis ,\n" - " Jeremy Tan "); - -PluginConfig* get_config () -{ - return &plugin_cfg; -} + const char GlobalHotkeys::about[] = N_( + "Global Hotkey Plugin\n" + "Control the player with global key combinations or multimedia " + "keys.\n\n" + "Copyright (C) 2007-2008 Sascha Hlusiak \n\n" + "Contributors include:\n" + "Copyright (C) 2006-2007 Vladimir Paskov \n" + "Copyright (C) 2000-2002 Ville Syrjälä ,\n" + " Bryn Davies ,\n" + " Jonathan A. Davis ,\n" + " Jeremy Tan "); + +PluginConfig * get_config() { return &plugin_cfg; } /* * plugin activated */ -bool GlobalHotkeys::init () +bool GlobalHotkeys::init() { #ifdef BUILT_FROM_CMAKE audlog::subscribe(&DCustomLogger::go, audlog::Level::Debug); #endif - if (! gtk_init_check (nullptr, nullptr)) + if (!gtk_init_check(nullptr, nullptr)) { - AUDERR ("GTK+ initialization failed.\n"); + AUDERR("GTK+ initialization failed.\n"); return false; } #ifdef _WIN32 - win_init(); + win_init(); #endif setup_filter(); - load_config ( ); - grab_keys (); + load_config(); + grab_keys(); return true; } /* handle keys */ -gboolean handle_keyevent (EVENT event) +gboolean handle_keyevent(EVENT event) { int current_volume, old_volume; static int volume_static = 0; gboolean mute; /* get current volume */ - current_volume = aud_drct_get_volume_main (); + current_volume = aud_drct_get_volume_main(); old_volume = current_volume; if (current_volume) { /* volume is not mute */ mute = false; - } else { + } + else + { /* volume is mute */ mute = true; } @@ -142,10 +138,12 @@ gboolean handle_keyevent (EVENT event) if (!mute) { volume_static = current_volume; - aud_drct_set_volume_main (0); + aud_drct_set_volume_main(0); mute = true; - } else { - aud_drct_set_volume_main (volume_static); + } + else + { + aud_drct_set_volume_main(volume_static); mute = false; } return true; @@ -161,14 +159,14 @@ gboolean handle_keyevent (EVENT event) mute = false; } - if ((current_volume -= aud_get_int ("volume_delta")) < 0) + if ((current_volume -= aud_get_int("volume_delta")) < 0) { current_volume = 0; } if (current_volume != old_volume) { - aud_drct_set_volume_main (current_volume); + aud_drct_set_volume_main(current_volume); } old_volume = current_volume; @@ -185,14 +183,14 @@ gboolean handle_keyevent (EVENT event) mute = false; } - if ((current_volume += aud_get_int ("volume_delta")) > 100) + if ((current_volume += aud_get_int("volume_delta")) > 100) { current_volume = 100; } if (current_volume != old_volume) { - aud_drct_set_volume_main (current_volume); + aud_drct_set_volume_main(current_volume); } old_volume = current_volume; @@ -202,63 +200,63 @@ gboolean handle_keyevent (EVENT event) /* play */ if (event == EVENT_PLAY) { - aud_drct_play (); + aud_drct_play(); return true; } /* pause */ if (event == EVENT_PAUSE) { - aud_drct_play_pause (); + aud_drct_play_pause(); return true; } /* stop */ if (event == EVENT_STOP) { - aud_drct_stop (); + aud_drct_stop(); return true; } /* prev track */ if (event == EVENT_PREV_TRACK) { - aud_drct_pl_prev (); + aud_drct_pl_prev(); return true; } /* next track */ if (event == EVENT_NEXT_TRACK) { - aud_drct_pl_next (); + aud_drct_pl_next(); return true; } /* forward */ if (event == EVENT_FORWARD) { - aud_drct_seek (aud_drct_get_time () + aud_get_int ("step_size") * 1000); + aud_drct_seek(aud_drct_get_time() + aud_get_int("step_size") * 1000); return true; } /* backward */ if (event == EVENT_BACKWARD) { - aud_drct_seek (aud_drct_get_time () - aud_get_int ("step_size") * 1000); + aud_drct_seek(aud_drct_get_time() - aud_get_int("step_size") * 1000); return true; } /* Open Jump-To-File dialog */ - if (event == EVENT_JUMP_TO_FILE && ! aud_get_headless_mode ()) + if (event == EVENT_JUMP_TO_FILE && !aud_get_headless_mode()) { - aud_ui_show_jump_to_song (); + aud_ui_show_jump_to_song(); return true; } /* Toggle Windows */ - if (event == EVENT_TOGGLE_WIN && ! aud_get_headless_mode ()) + if (event == EVENT_TOGGLE_WIN && !aud_get_headless_mode()) { - aud_ui_show (! aud_ui_is_shown ()); + aud_ui_show(!aud_ui_is_shown()); return true; } @@ -271,126 +269,136 @@ gboolean handle_keyevent (EVENT event) if (event == EVENT_TOGGLE_REPEAT) { - aud_toggle_bool ("repeat"); + aud_toggle_bool("repeat"); return true; } if (event == EVENT_TOGGLE_SHUFFLE) { - aud_toggle_bool ("shuffle"); + aud_toggle_bool("shuffle"); return true; } if (event == EVENT_TOGGLE_STOP) { - aud_toggle_bool ("stop_after_current_song"); + aud_toggle_bool("stop_after_current_song"); return true; } if (event == EVENT_RAISE) { - aud_ui_show (true); + aud_ui_show(true); return true; } return false; } -void load_defaults () +void load_defaults() { - AUDDBG("lHotkeyFlow:Entry, loading defaults."); - HotkeyConfiguration* hotkey; + AUDDBG("lHotkeyFlow:Entry, loading defaults."); + HotkeyConfiguration * hotkey; hotkey = &(plugin_cfg.first); - Hotkey::add_hotkey(&hotkey, OS_KEY_AudioPrev, 0, TYPE_KEY, EVENT_PREV_TRACK); - Hotkey::add_hotkey(&hotkey, OS_KEY_AudioPlay, 0, TYPE_KEY, EVENT_PLAY); - Hotkey::add_hotkey(&hotkey, OS_KEY_AudioPause, 0, TYPE_KEY, EVENT_PAUSE); - Hotkey::add_hotkey(&hotkey, OS_KEY_AudioStop, 0, TYPE_KEY, EVENT_STOP); - Hotkey::add_hotkey(&hotkey, OS_KEY_AudioNext, 0, TYPE_KEY, EVENT_NEXT_TRACK); - -/* add_hotkey(&hotkey, OS_KEY_AudioRewind, 0, TYPE_KEY, EVENT_BACKWARD); */ - - Hotkey::add_hotkey(&hotkey, OS_KEY_AudioMute, 0, TYPE_KEY, EVENT_MUTE); - Hotkey::add_hotkey(&hotkey, OS_KEY_AudioRaiseVolume, 0, TYPE_KEY, EVENT_VOL_UP); - Hotkey::add_hotkey(&hotkey, OS_KEY_AudioLowerVolume, 0, TYPE_KEY, EVENT_VOL_DOWN); - -/* add_hotkey(&hotkey, OS_KEY_AudioMedia, 0, TYPE_KEY, EVENT_JUMP_TO_FILE); - add_hotkey(&hotkey, XF86XK_Music, 0, TYPE_KEY, EVENT_TOGGLE_WIN); */ + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioPrev, 0, TYPE_KEY, + EVENT_PREV_TRACK); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioPlay, 0, TYPE_KEY, EVENT_PLAY); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioPause, 0, TYPE_KEY, EVENT_PAUSE); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioStop, 0, TYPE_KEY, EVENT_STOP); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioNext, 0, TYPE_KEY, + EVENT_NEXT_TRACK); + + /* add_hotkey(&hotkey, OS_KEY_AudioRewind, 0, TYPE_KEY, EVENT_BACKWARD); + */ + + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioMute, 0, TYPE_KEY, EVENT_MUTE); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioRaiseVolume, 0, TYPE_KEY, + EVENT_VOL_UP); + Hotkey::add_hotkey(&hotkey, OS_KEY_AudioLowerVolume, 0, TYPE_KEY, + EVENT_VOL_DOWN); + + /* add_hotkey(&hotkey, OS_KEY_AudioMedia, 0, TYPE_KEY, + EVENT_JUMP_TO_FILE); add_hotkey(&hotkey, XF86XK_Music, 0, TYPE_KEY, + EVENT_TOGGLE_WIN); */ } /* load plugin configuration */ -void load_config () +void load_config() { - HotkeyConfiguration *hotkey; - int i,max; + HotkeyConfiguration * hotkey; + int i, max; hotkey = &(plugin_cfg.first); hotkey->next = nullptr; hotkey->key = 0; hotkey->mask = 0; - hotkey->event = (EVENT) 0; + hotkey->event = (EVENT)0; hotkey->type = TYPE_KEY; - max = aud_get_int ("globalHotkey", "NumHotkeys"); + max = aud_get_int("globalHotkey", "NumHotkeys"); if (max == 0) load_defaults(); - else for (i=0; ikey) { - hotkey->next = g_new(HotkeyConfiguration, 1); - hotkey = hotkey->next; - hotkey->next = nullptr; - hotkey->key = 0; - hotkey->mask = 0; - hotkey->event = (EVENT) 0; - hotkey->type = TYPE_KEY; - } - text = g_strdup_printf("Hotkey_%d_key", i); - hotkey->key = aud_get_int ("globalHotkey", text); - g_free(text); + else + for (i = 0; i < max; i++) + { + char * text = nullptr; + + if (hotkey->key) + { + hotkey->next = g_new(HotkeyConfiguration, 1); + hotkey = hotkey->next; + hotkey->next = nullptr; + hotkey->key = 0; + hotkey->mask = 0; + hotkey->event = (EVENT)0; + hotkey->type = TYPE_KEY; + } + text = g_strdup_printf("Hotkey_%d_key", i); + hotkey->key = aud_get_int("globalHotkey", text); + g_free(text); - text = g_strdup_printf("Hotkey_%d_mask", i); - hotkey->mask = aud_get_int ("globalHotkey", text); - g_free(text); + text = g_strdup_printf("Hotkey_%d_mask", i); + hotkey->mask = aud_get_int("globalHotkey", text); + g_free(text); - text = g_strdup_printf("Hotkey_%d_type", i); - hotkey->type = aud_get_int ("globalHotkey", text); - g_free(text); + text = g_strdup_printf("Hotkey_%d_type", i); + hotkey->type = aud_get_int("globalHotkey", text); + g_free(text); - text = g_strdup_printf("Hotkey_%d_event", i); - hotkey->event = (EVENT) aud_get_int ("globalHotkey", text); - g_free(text); - } + text = g_strdup_printf("Hotkey_%d_event", i); + hotkey->event = (EVENT)aud_get_int("globalHotkey", text); + g_free(text); + } } /* save plugin configuration */ -void save_config () +void save_config() { int max; - HotkeyConfiguration *hotkey; + HotkeyConfiguration * hotkey; hotkey = &(plugin_cfg.first); max = 0; - while (hotkey) { - char *text = nullptr; - if (hotkey->key) { + while (hotkey) + { + char * text = nullptr; + if (hotkey->key) + { text = g_strdup_printf("Hotkey_%d_key", max); - aud_set_int ("globalHotkey", text, hotkey->key); + aud_set_int("globalHotkey", text, hotkey->key); g_free(text); text = g_strdup_printf("Hotkey_%d_mask", max); - aud_set_int ("globalHotkey", text, hotkey->mask); + aud_set_int("globalHotkey", text, hotkey->mask); g_free(text); text = g_strdup_printf("Hotkey_%d_type", max); - aud_set_int ("globalHotkey", text, hotkey->type); + aud_set_int("globalHotkey", text, hotkey->type); g_free(text); text = g_strdup_printf("Hotkey_%d_event", max); - aud_set_int ("globalHotkey", text, hotkey->event); + aud_set_int("globalHotkey", text, hotkey->event); g_free(text); max++; } @@ -398,18 +406,18 @@ void save_config () hotkey = hotkey->next; } - aud_set_int ("globalHotkey", "NumHotkeys", max); + aud_set_int("globalHotkey", "NumHotkeys", max); } -void GlobalHotkeys::cleanup () +void GlobalHotkeys::cleanup() { #ifdef BUILT_FROM_CMAKE audlog::unsubscribe(&DCustomLogger::go); #endif - HotkeyConfiguration* hotkey; - ungrab_keys (); - release_filter(); + HotkeyConfiguration * hotkey; + ungrab_keys(); + release_filter(); hotkey = &(plugin_cfg.first); hotkey = hotkey->next; while (hotkey) @@ -421,6 +429,6 @@ void GlobalHotkeys::cleanup () } plugin_cfg.first.next = nullptr; plugin_cfg.first.key = 0; - plugin_cfg.first.event = (EVENT) 0; + plugin_cfg.first.event = (EVENT)0; plugin_cfg.first.mask = 0; } diff --git a/src/hotkey/plugin.h b/src/hotkey/plugin.h index 664f257b51..7b2c601318 100644 --- a/src/hotkey/plugin.h +++ b/src/hotkey/plugin.h @@ -25,8 +25,8 @@ #define HK_MOD5_MASK Mod5Mask #endif - -typedef enum { +typedef enum +{ EVENT_PREV_TRACK = 0, EVENT_PLAY, EVENT_PAUSE, @@ -51,24 +51,23 @@ typedef enum { EVENT_MAX } EVENT; - -typedef struct _HotkeyConfiguration { +typedef struct _HotkeyConfiguration +{ unsigned key, mask; unsigned type; EVENT event; - struct _HotkeyConfiguration *next; + struct _HotkeyConfiguration * next; } HotkeyConfiguration; -typedef struct { +typedef struct +{ /* keyboard */ HotkeyConfiguration first; } PluginConfig; - - -void load_config (); -void save_config (); -PluginConfig* get_config (); +void load_config(); +void save_config(); +PluginConfig * get_config(); gboolean handle_keyevent(EVENT event); #ifdef _WIN32 void win_init(); diff --git a/src/hotkey/x_hotkey.cc b/src/hotkey/x_hotkey.cc index d668f8eaba..f1a4edd1e5 100644 --- a/src/hotkey/x_hotkey.cc +++ b/src/hotkey/x_hotkey.cc @@ -1,37 +1,50 @@ #include -#include #include +#include #include #include "api_hotkey.h" -void Hotkey::add_hotkey(HotkeyConfiguration **pphotkey, OS_KeySym keysym, int mask, int type, EVENT event) { - KeyCode keycode; - HotkeyConfiguration *photkey; - if (keysym == 0) return; - if (pphotkey == nullptr) return; - photkey = *pphotkey; - if (photkey == nullptr) return; - keycode = XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym); - if (keycode == 0) return; - if (photkey->key) { - photkey->next = g_new(HotkeyConfiguration, 1); - photkey = photkey->next; - *pphotkey = photkey; - photkey->next = nullptr; - } - photkey->key = (int) keycode; - photkey->mask = mask; - photkey->event = event; - photkey->type = type; +void Hotkey::add_hotkey(HotkeyConfiguration ** pphotkey, OS_KeySym keysym, + int mask, int type, EVENT event) +{ + KeyCode keycode; + HotkeyConfiguration * photkey; + if (keysym == 0) + return; + if (pphotkey == nullptr) + return; + photkey = *pphotkey; + if (photkey == nullptr) + return; + keycode = XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), + keysym); + if (keycode == 0) + return; + if (photkey->key) + { + photkey->next = g_new(HotkeyConfiguration, 1); + photkey = photkey->next; + *pphotkey = photkey; + photkey->next = nullptr; + } + photkey->key = (int)keycode; + photkey->mask = mask; + photkey->event = event; + photkey->type = type; } -void Hotkey::key_to_string(int key, char **out_keytext) { - KeySym keysym; - keysym = XkbKeycodeToKeysym(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), key, 0, 0); - if (keysym == 0 || keysym == NoSymbol) { - *out_keytext = g_strdup_printf("#%d", key); - } else { - *out_keytext = g_strdup(XKeysymToString(keysym)); - } +void Hotkey::key_to_string(int key, char ** out_keytext) +{ + KeySym keysym; + keysym = XkbKeycodeToKeysym(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), + key, 0, 0); + if (keysym == 0 || keysym == NoSymbol) + { + *out_keytext = g_strdup_printf("#%d", key); + } + else + { + *out_keytext = g_strdup(XKeysymToString(keysym)); + } } \ No newline at end of file diff --git a/src/hotkeyw32/w32_grab.cc b/src/hotkeyw32/w32_grab.cc index 576e6c7023..4dc750ac75 100644 --- a/src/hotkeyw32/w32_grab.cc +++ b/src/hotkeyw32/w32_grab.cc @@ -1,6 +1,5 @@ - #include "../hotkey/grab.h" #include @@ -12,9 +11,5 @@ #include "../hotkey/plugin.h" -void grab_keys (){ - AUDDBG("lHotkeyFlow:w_grab: grab_keys"); -} -void ungrab_keys (){ - AUDDBG("lHotkeyFlow:w_grab: ungrab_keys"); -} \ No newline at end of file +void grab_keys() { AUDDBG("lHotkeyFlow:w_grab: grab_keys"); } +void ungrab_keys() { AUDDBG("lHotkeyFlow:w_grab: ungrab_keys"); } \ No newline at end of file diff --git a/src/hotkeyw32/w32_hotkey.cc b/src/hotkeyw32/w32_hotkey.cc index b3cb916391..c220925691 100644 --- a/src/hotkeyw32/w32_hotkey.cc +++ b/src/hotkeyw32/w32_hotkey.cc @@ -2,17 +2,17 @@ #include -#include #include +#include -#include -#include -#include -#include -#include -#include #include +#include #include +#include +#include +#include +#include +#include #include "windows_key_str_map.h" @@ -22,56 +22,69 @@ constexpr auto W_KEY_ID_NEXT = 18773; constexpr auto W_FIRST_GLOBAL_KEY_ID = 18774; template -std::string VirtualKeyCodeToStringMethod2(T virtualKey) { - WCHAR name[128]; - static auto key_layout = GetKeyboardLayout(0); - UINT scanCode = MapVirtualKeyEx(virtualKey, MAPVK_VK_TO_VSC, key_layout); - LONG lParamValue = (scanCode << 16); - int result = GetKeyNameTextW(lParamValue, name, 1024); - if (result > 0) { - auto *windows_cmd = reinterpret_cast(g_utf16_to_utf8( - reinterpret_cast (name), - -1, nullptr, nullptr, nullptr)); - std::string returning(windows_cmd); - g_free(windows_cmd); - return returning; - } else { - return {}; - } +std::string VirtualKeyCodeToStringMethod2(T virtualKey) +{ + WCHAR name[128]; + static auto key_layout = GetKeyboardLayout(0); + UINT scanCode = MapVirtualKeyEx(virtualKey, MAPVK_VK_TO_VSC, key_layout); + LONG lParamValue = (scanCode << 16); + int result = GetKeyNameTextW(lParamValue, name, 1024); + if (result > 0) + { + auto * windows_cmd = reinterpret_cast( + g_utf16_to_utf8(reinterpret_cast(name), -1, + nullptr, nullptr, nullptr)); + std::string returning(windows_cmd); + g_free(windows_cmd); + return returning; + } + else + { + return {}; + } } -void Hotkey::add_hotkey(HotkeyConfiguration **pphotkey, Hotkey::OS_KeySym keysym, int mask, int type, EVENT event) { - AUDDBG("lHotkeyFlow:Win call."); - HotkeyConfiguration *photkey; - if (keysym == 0) return; - if (pphotkey == nullptr) return; - photkey = *pphotkey; - if (photkey == nullptr) return; - // keycode = XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), keysym); - // if (keycode == 0) return; - if (photkey->key) { - photkey->next = g_new(HotkeyConfiguration, 1); - photkey = photkey->next; - *pphotkey = photkey; - photkey->next = nullptr; - } - photkey->key = (int) 42; - photkey->mask = mask; - photkey->event = event; - photkey->type = type; +void Hotkey::add_hotkey(HotkeyConfiguration ** pphotkey, + Hotkey::OS_KeySym keysym, int mask, int type, + EVENT event) +{ + AUDDBG("lHotkeyFlow:Win call."); + HotkeyConfiguration * photkey; + if (keysym == 0) + return; + if (pphotkey == nullptr) + return; + photkey = *pphotkey; + if (photkey == nullptr) + return; + // keycode = + // XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), + // keysym); if (keycode == 0) return; + if (photkey->key) + { + photkey->next = g_new(HotkeyConfiguration, 1); + photkey = photkey->next; + *pphotkey = photkey; + photkey->next = nullptr; + } + photkey->key = (int)42; + photkey->mask = mask; + photkey->event = event; + photkey->type = type; } -void register_global_keys(HWND handle){ - auto * hotkey = &(plugin_cfg.first); - auto _id = W_FIRST_GLOBAL_KEY_ID; - while (hotkey) - { - RegisterHotKey(handle, _id++, hotkey->mask, hotkey->key); - hotkey = hotkey->next; - } +void register_global_keys(HWND handle) +{ + auto * hotkey = &(plugin_cfg.first); + auto _id = W_FIRST_GLOBAL_KEY_ID; + while (hotkey) + { + RegisterHotKey(handle, _id++, hotkey->mask, hotkey->key); + hotkey = hotkey->next; + } } -//void assign(wchar_t *ptr_first_element, const wchar_t *text) { +// void assign(wchar_t *ptr_first_element, const wchar_t *text) { // int loc = 0; // while (text[loc]) { // ptr_first_element[loc] = text[loc]; @@ -80,130 +93,129 @@ void register_global_keys(HWND handle){ // ptr_first_element[loc] = 0; //} -HRESULT AddThumbarButtons(HWND hwnd) { - // Define an array of two buttons. These buttons provide images through an - // image list and also provide tooltips. - THUMBBUTTONMASK dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS; - - /* - THUMBBUTTONMASK dwMask; - UINT iId; - UINT iBitmap; - HICON hIcon; - WCHAR szTip[260]; - THUMBBUTTONFLAGS dwFlags; - */ +HRESULT AddThumbarButtons(HWND hwnd) +{ + // Define an array of two buttons. These buttons provide images through an + // image list and also provide tooltips. + THUMBBUTTONMASK dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS; + /* + THUMBBUTTONMASK dwMask; + UINT iId; + UINT iBitmap; + HICON hIcon; + WCHAR szTip[260]; + THUMBBUTTONFLAGS dwFlags; + */ - THUMBBUTTON btn[]{{ - dwMask, - W_KEY_ID_PREV, - 0, - nullptr, - L"Previous song", - THBF_ENABLED - }, - { - dwMask, - W_KEY_ID_PLAY, - 0, - nullptr, - L"Play/pause", - THBF_ENABLED - }, - { - dwMask, - W_KEY_ID_NEXT, - 0, - nullptr, - L"Next song", - THBF_ENABLED - } - }; + THUMBBUTTON btn[]{ + {dwMask, W_KEY_ID_PREV, 0, nullptr, L"Previous song", THBF_ENABLED}, + {dwMask, W_KEY_ID_PLAY, 0, nullptr, L"Play/pause", THBF_ENABLED}, + {dwMask, W_KEY_ID_NEXT, 0, nullptr, L"Next song", THBF_ENABLED}}; - ITaskbarList3 *ptbl; - HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, - IID_PPV_ARGS(&ptbl)); + ITaskbarList3 * ptbl; + HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&ptbl)); - if (SUCCEEDED(hr)) { - // Declare the image list that contains the button images. - // hr = ptbl->ThumbBarSetImageList(hwnd, himl); + if (SUCCEEDED(hr)) + { + // Declare the image list that contains the button images. + // hr = ptbl->ThumbBarSetImageList(hwnd, himl); - if (SUCCEEDED(hr)) { - // Attach the toolbar to the thumbnail. - hr = ptbl->ThumbBarAddButtons(hwnd, ARRAYSIZE(btn), btn); + if (SUCCEEDED(hr)) + { + // Attach the toolbar to the thumbnail. + hr = ptbl->ThumbBarAddButtons(hwnd, ARRAYSIZE(btn), btn); + } + ptbl->Release(); } - ptbl->Release(); - } - return hr; + return hr; } -GdkFilterReturn buttons_evts_filter(GdkXEvent *gdk_xevent, GdkEvent *event, - gpointer user_data) { - auto msg = reinterpret_cast(gdk_xevent); - if (msg->message == WM_COMMAND) { - auto buttonId = static_cast(msg->wParam & 0xFFFF); - AUDDBG("Clicked button with ID: %d", buttonId); - switch (buttonId) { - case W_KEY_ID_PLAY:handle_keyevent(EVENT_PAUSE); - break; - case W_KEY_ID_NEXT :handle_keyevent(EVENT_NEXT_TRACK); - break; - case W_KEY_ID_PREV:handle_keyevent(EVENT_PREV_TRACK); +GdkFilterReturn buttons_evts_filter(GdkXEvent * gdk_xevent, GdkEvent * event, + gpointer user_data) +{ + auto msg = reinterpret_cast(gdk_xevent); + if (msg->message == WM_COMMAND) + { + auto buttonId = static_cast(msg->wParam & 0xFFFF); + AUDDBG("Clicked button with ID: %d", buttonId); + switch (buttonId) + { + case W_KEY_ID_PLAY: + handle_keyevent(EVENT_PAUSE); + break; + case W_KEY_ID_NEXT: + handle_keyevent(EVENT_NEXT_TRACK); + break; + case W_KEY_ID_PREV: + handle_keyevent(EVENT_PREV_TRACK); + } + return GDK_FILTER_REMOVE; } - return GDK_FILTER_REMOVE; - } - if (msg->message == WM_HOTKEY) { - auto k_id = static_cast(msg->wParam & 0xFFFF); - AUDDBG("lHotkeyFlow:Global hotkey: %d" , k_id); - // Max 20 HKs - if(k_id >= W_FIRST_GLOBAL_KEY_ID && k_id < W_FIRST_GLOBAL_KEY_ID + 20){ - auto idx = k_id - W_FIRST_GLOBAL_KEY_ID; - auto * config = &plugin_cfg.first; - while(idx--){ - config = config->next; - } - handle_keyevent(config->event); + if (msg->message == WM_HOTKEY) + { + auto k_id = static_cast(msg->wParam & 0xFFFF); + AUDDBG("lHotkeyFlow:Global hotkey: %d", k_id); + // Max 20 HKs + if (k_id >= W_FIRST_GLOBAL_KEY_ID && k_id < W_FIRST_GLOBAL_KEY_ID + 20) + { + auto idx = k_id - W_FIRST_GLOBAL_KEY_ID; + auto * config = &plugin_cfg.first; + while (idx--) + { + config = config->next; + } + handle_keyevent(config->event); + } } - } - return GDK_FILTER_CONTINUE; + return GDK_FILTER_CONTINUE; } -struct EnumWindowsCallbackArgs { - explicit EnumWindowsCallbackArgs(DWORD p) : pid(p) {} - const DWORD pid; - std::vector handles; +struct EnumWindowsCallbackArgs +{ + explicit EnumWindowsCallbackArgs(DWORD p) : pid(p) {} + const DWORD pid; + std::vector handles; }; -static BOOL CALLBACK EnumWindowsCallback(HWND hnd, LPARAM lParam) { - // Get pointer to created callback object for storing data. - auto *args = reinterpret_cast ( lParam); - // Callback result are all windows (not only my program). I filter by PID / thread ID. - DWORD windowPID; - GetWindowThreadProcessId(hnd, &windowPID); - // Compare to the one we have stored in our callbaack structure. - if (windowPID == args->pid) { - args->handles.push_back(hnd); - } +static BOOL CALLBACK EnumWindowsCallback(HWND hnd, LPARAM lParam) +{ + // Get pointer to created callback object for storing data. + auto * args = reinterpret_cast(lParam); + // Callback result are all windows (not only my program). I filter by PID / + // thread ID. + DWORD windowPID; + GetWindowThreadProcessId(hnd, &windowPID); + // Compare to the one we have stored in our callbaack structure. + if (windowPID == args->pid) + { + args->handles.push_back(hnd); + } - return TRUE; + return TRUE; } -std::vector getToplevelWindows() { - // Create object that will hold a result. - EnumWindowsCallbackArgs args(GetCurrentProcessId()); - // AUDERR("Testing getlasterror: %ld\n.", GetLastError()); - // Call EnumWindows and pass pointer to function and created callback structure. - if (EnumWindows(&EnumWindowsCallback, (LPARAM) &args) == FALSE) { - // If the call fails, return empty vector - AUDERR("WinApiError (code %ld). Cannot get windows, hotkey plugin won't work.\n", GetLastError()); - return std::vector(); - } - // Otherwise, callback function filled the struct. Return important data. - // Test: GetActiveWindow - args.handles.push_back(GetActiveWindow()); - args.handles.push_back(GetForegroundWindow()); - return args.handles; +std::vector getToplevelWindows() +{ + // Create object that will hold a result. + EnumWindowsCallbackArgs args(GetCurrentProcessId()); + // AUDERR("Testing getlasterror: %ld\n.", GetLastError()); + // Call EnumWindows and pass pointer to function and created callback + // structure. + if (EnumWindows(&EnumWindowsCallback, (LPARAM)&args) == FALSE) + { + // If the call fails, return empty vector + AUDERR("WinApiError (code %ld). Cannot get windows, hotkey plugin " + "won't work.\n", + GetLastError()); + return std::vector(); + } + // Otherwise, callback function filled the struct. Return important data. + // Test: GetActiveWindow + args.handles.push_back(GetActiveWindow()); + args.handles.push_back(GetForegroundWindow()); + return args.handles; } /** @@ -217,55 +229,63 @@ std::vector getToplevelWindows() { * Returns: %FALSE if the source should be removed. #G_SOURCE_CONTINUE and * #G_SOURCE_REMOVE are more memorable names for the return value. */ -gboolean window_created_callback(gpointer user_data) { +gboolean window_created_callback(gpointer user_data) +{ - AUDDBG("lHotkeyFlow:Window created. Do real stuff."); - auto wins = getToplevelWindows(); - AUDDBG("lHotkeyFlow:windows: %zu" ,wins.size()); - for (auto win : wins) { - wchar_t className[311]; - GetClassNameW(win, className, _countof(className)); - auto s_cn = reinterpret_cast(g_utf16_to_utf8( - reinterpret_cast (className), - -1, nullptr, nullptr, nullptr)); + AUDDBG("lHotkeyFlow:Window created. Do real stuff."); + auto wins = getToplevelWindows(); + AUDDBG("lHotkeyFlow:windows: %zu", wins.size()); + for (auto win : wins) + { + wchar_t className[311]; + GetClassNameW(win, className, _countof(className)); + auto s_cn = reinterpret_cast( + g_utf16_to_utf8(reinterpret_cast(className), -1, + nullptr, nullptr, nullptr)); - GetWindowTextW(win, className, _countof(className)); - auto s_cn2 = reinterpret_cast(g_utf16_to_utf8( - reinterpret_cast (className), - -1, nullptr, nullptr, nullptr)); - if (s_cn) { - AUDDBG("lHotkeyFlow:WIN: %s%s", s_cn, ([s_cn2]() { - std::string returning{}; - if (s_cn2) { - returning = std::string(" titled: ") + s_cn2; - g_free(s_cn2); + GetWindowTextW(win, className, _countof(className)); + auto s_cn2 = reinterpret_cast( + g_utf16_to_utf8(reinterpret_cast(className), -1, + nullptr, nullptr, nullptr)); + if (s_cn) + { + AUDDBG("lHotkeyFlow:WIN: %s%s", s_cn, + ([s_cn2]() { + std::string returning{}; + if (s_cn2) + { + returning = std::string(" titled: ") + s_cn2; + g_free(s_cn2); + } + return returning; + }()) + .c_str()); + g_free(s_cn); } - return returning; - }()).c_str()); - g_free(s_cn); } - } - auto the_hwnd = wins.back(); - // AddThumbarButtons(the_hwnd); Disabled for now ... first get hotkeys perfectly stable - auto gdkwin = gdk_win32_handle_table_lookup(the_hwnd); - gdk_window_add_filter((GdkWindow *) gdkwin, buttons_evts_filter, - nullptr); - register_global_keys(the_hwnd); - return false; + auto the_hwnd = wins.back(); + // AddThumbarButtons(the_hwnd); Disabled for now ... first get hotkeys + // perfectly stable + auto gdkwin = gdk_win32_handle_table_lookup(the_hwnd); + gdk_window_add_filter((GdkWindow *)gdkwin, buttons_evts_filter, nullptr); + register_global_keys(the_hwnd); + return false; } -void win_init() { - AUDDBG("lHotkeyFlow:Win .. important call."); - g_idle_add(&window_created_callback, - nullptr); +void win_init() +{ + AUDDBG("lHotkeyFlow:Win .. important call."); + g_idle_add(&window_created_callback, nullptr); } - -void Hotkey::key_to_string(int key, char **out_keytext) { - // Special handling for most OEM keys - they may depend on language or keyboard? - switch (key) { +void Hotkey::key_to_string(int key, char ** out_keytext) +{ + // Special handling for most OEM keys - they may depend on language or + // keyboard? + switch (key) + { case VK_OEM_NEC_EQUAL: - // case VK_OEM_FJ_JISHO: (note: same as EQUAL) + // case VK_OEM_FJ_JISHO: (note: same as EQUAL) case VK_OEM_FJ_MASSHOU: case VK_OEM_FJ_TOUROKU: case VK_OEM_FJ_LOYA: @@ -293,13 +313,15 @@ void Hotkey::key_to_string(int key, char **out_keytext) { case VK_OEM_AUTO: case VK_OEM_ENLW: case VK_OEM_BACKTAB: - case VK_OEM_CLEAR: { - auto win_str = VirtualKeyCodeToStringMethod2(key); - if (!win_str.empty()) { - *out_keytext = g_strdup(win_str.c_str()); - return; - } + case VK_OEM_CLEAR: + { + auto win_str = VirtualKeyCodeToStringMethod2(key); + if (!win_str.empty()) + { + *out_keytext = g_strdup(win_str.c_str()); + return; + } + } } - } - *out_keytext = g_strdup(WIN_VK_NAMES[key]); + *out_keytext = g_strdup(WIN_VK_NAMES[key]); } \ No newline at end of file diff --git a/src/hotkeyw32/windows_key_str_map.h b/src/hotkeyw32/windows_key_str_map.h index bb40783a58..ccb7ae4648 100644 --- a/src/hotkeyw32/windows_key_str_map.h +++ b/src/hotkeyw32/windows_key_str_map.h @@ -4,7 +4,7 @@ // https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes // As defined in WinUser.h -constexpr const char *const WIN_VK_NAMES[] = { +constexpr const char * const WIN_VK_NAMES[] = { "UNKNOWN_KEY: 0", "LBUTTON", "RBUTTON", @@ -260,7 +260,6 @@ constexpr const char *const WIN_VK_NAMES[] = { "NONAME", "PA1", "OEM_CLEAR", - "UNKNOWN_KEY: 255" -}; + "UNKNOWN_KEY: 255"}; -#endif //AUDACIOUS_PLUGINS_WINDOWS_KEY_STRINGS_HPP +#endif // AUDACIOUS_PLUGINS_WINDOWS_KEY_STRINGS_HPP From d1b89e2ef2166bb917d93ff74691c4ceb444d6fd Mon Sep 17 00:00:00 2001 From: Domen Mori Date: Fri, 4 Sep 2020 21:48:14 +0200 Subject: [PATCH 3/4] GTK global hotkeys for Windows --- src/hotkey/api_hotkey.h | 28 ++ src/hotkey/grab.h | 27 ++ src/hotkey/gui.cc | 20 +- src/hotkey/gui.h | 27 ++ src/hotkey/hotkey_api_common.cc | 50 ++-- src/hotkey/plugin.cc | 70 ++--- src/hotkey/plugin.h | 38 ++- src/hotkey/x_hotkey.cc | 48 ++++ src/hotkeyw32/Makefile | 2 +- src/hotkeyw32/w32_grab.cc | 15 - src/hotkeyw32/w32_hotkey.cc | 411 +++++++++++++++++++--------- src/hotkeyw32/windows_key_str_map.h | 27 ++ src/hotkeyw32/windows_window.cc | 316 +++++++++++++++++++++ src/hotkeyw32/windows_window.h | 105 +++++++ 14 files changed, 970 insertions(+), 214 deletions(-) delete mode 100644 src/hotkeyw32/w32_grab.cc create mode 100644 src/hotkeyw32/windows_window.cc create mode 100644 src/hotkeyw32/windows_window.h diff --git a/src/hotkey/api_hotkey.h b/src/hotkey/api_hotkey.h index ec80d6d69b..0d2e563ab3 100644 --- a/src/hotkey/api_hotkey.h +++ b/src/hotkey/api_hotkey.h @@ -1,3 +1,30 @@ +/* + * api_hotkey.h + * Audacious + * + * Copyright (C) 2005-2020 Audacious team + * + * XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, + * Thomas Nilsson and 4Front Technologies + * Copyright (C) 1999-2003 Haavard Kvaalen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. +*/ + #ifndef _X_HOTKEY_H_INCLUDED #define _X_HOTKEY_H_INCLUDED @@ -32,6 +59,7 @@ class Hotkey static void add_hotkey(HotkeyConfiguration ** pphotkey, OS_KeySym keysym, int mask, int type, EVENT event); static void key_to_string(int key, char ** out_keytext); + static char* create_human_readable_keytext(const char* const keytext, int key, int mask); }; #ifndef _WIN32 diff --git a/src/hotkey/grab.h b/src/hotkey/grab.h index 47935dbbd3..c416345aef 100644 --- a/src/hotkey/grab.h +++ b/src/hotkey/grab.h @@ -1,3 +1,30 @@ +/* + * grab.h + * Audacious + * + * Copyright (C) 2005-2020 Audacious team + * + * XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, + * Thomas Nilsson and 4Front Technologies + * Copyright (C) 1999-2003 Haavard Kvaalen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. +*/ + #ifndef _GRAB_H_INCLUDED_ #define _GRAB_H_INCLUDED_ diff --git a/src/hotkey/gui.cc b/src/hotkey/gui.cc index 43bf977cb2..362ce2637f 100644 --- a/src/hotkey/gui.cc +++ b/src/hotkey/gui.cc @@ -2,8 +2,8 @@ * This file is part of audacious-hotkey plugin for audacious * * Copyright (c) 2007 - 2008 Sascha Hlusiak - * Name: gui.c - * Description: gui.c + * Name: gui.cc + * Description: gui.cc * * Part of this code is from itouch-ctrl plugin. * Authors of itouch-ctrl are listed below: @@ -90,7 +90,6 @@ static const char * event_desc[EVENT_MAX] = { static gboolean on_entry_key_press_event(GtkWidget * widget, GdkEventKey * event, void * user_data) { - AUDDBG("lHotkeyFlow:Entry"); KeyControls * controls = (KeyControls *)user_data; if (event->keyval == GDK_Tab) @@ -99,6 +98,10 @@ static gboolean on_entry_key_press_event(GtkWidget * widget, return false; if (event->keyval == GDK_Return && ((event->state & ~GDK_LOCK_MASK) == 0)) return false; +#ifdef _WIN32 + if (event->keyval == GDK_Meta_L || event->keyval == GDK_Meta_R) + return false; +#endif if (event->keyval == GDK_ISO_Left_Tab) { Hotkey::set_keytext(controls->keytext, controls->hotkey.key, @@ -126,7 +129,7 @@ static gboolean on_entry_key_press_event(GtkWidget * widget, Hotkey::set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod, TYPE_KEY); - AUDDBG("lHotkeyFlow:Leave"); + // Returning TRUE indicates that the event has been handled, and that it should not propagate further. return true; } @@ -299,11 +302,7 @@ void * make_config_widget() load_config(); plugin_cfg = get_config(); - - // NOTE d: implement in WIN -#ifndef _WIN32 ungrab_keys(); -#endif main_vbox = gtk_vbox_new(false, 4); @@ -503,12 +502,7 @@ void add_callback(GtkWidget * widget, void * data) void destroy_callback() { KeyControls * controls = first_controls; - - // NOTE d: implement in WIN -#ifndef _WIN32 grab_keys(); -#endif - while (controls) { KeyControls * old; diff --git a/src/hotkey/gui.h b/src/hotkey/gui.h index 78e6562d8b..8dcced0936 100644 --- a/src/hotkey/gui.h +++ b/src/hotkey/gui.h @@ -1,3 +1,30 @@ +/* + * gui.h + * Audacious + * + * Copyright (C) 2005-2020 Audacious team + * + * XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, + * Thomas Nilsson and 4Front Technologies + * Copyright (C) 1999-2003 Haavard Kvaalen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. +*/ + #ifndef _GUI_H_INCLUDED_ #define _GUI_H_INCLUDED_ diff --git a/src/hotkey/hotkey_api_common.cc b/src/hotkey/hotkey_api_common.cc index eb59c912c8..338a8e8911 100644 --- a/src/hotkey/hotkey_api_common.cc +++ b/src/hotkey/hotkey_api_common.cc @@ -1,4 +1,29 @@ - +/* + * hotkey_api_common.cc + * Audacious + * + * Copyright (C) 2005-2020 Audacious team + * + * XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, + * Thomas Nilsson and 4Front Technologies + * Copyright (C) 1999-2003 Haavard Kvaalen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. +*/ #include "api_hotkey.h" #include @@ -38,10 +63,6 @@ template int Hotkey::calculate_mod(GdkEventButton * event); std::pair Hotkey::get_is_mod(GdkEventKey * event) { -#ifdef _WIN32 - AUDDBG("lHotkeyFlow:Win call: get_is_mod.%s", - gdk_keyval_name(event->keyval)); -#endif int mod = 0; int is_mod = 0; @@ -83,14 +104,7 @@ void Hotkey::set_keytext(GtkWidget * entry, int key, int mask, int type) } else { - static const char * modifier_string[] = { - "Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5"}; - static const unsigned int modifiers[] = { - HK_CONTROL_MASK, HK_SHIFT_MASK, HK_MOD1_ALT_MASK, HK_MOD2_MASK, - HK_MOD3_MASK, HK_MOD4_MASK, HK_MOD5_MASK}; - const char * strings[9]; char * keytext = nullptr; - int i, j; if (type == TYPE_KEY) { Hotkey::key_to_string(key, &keytext); @@ -99,17 +113,7 @@ void Hotkey::set_keytext(GtkWidget * entry, int key, int mask, int type) { keytext = g_strdup_printf("Button%d", key); } - - for (i = 0, j = 0; j < 7; j++) - { - if (mask & modifiers[j]) - strings[i++] = modifier_string[j]; - } - if (key != 0) - strings[i++] = keytext; - strings[i] = nullptr; - - text = g_strjoinv(" + ", (char **)strings); + text = Hotkey::create_human_readable_keytext(keytext, key, mask); g_free(keytext); } diff --git a/src/hotkey/plugin.cc b/src/hotkey/plugin.cc index 6b05267b6f..f6e91f64fd 100644 --- a/src/hotkey/plugin.cc +++ b/src/hotkey/plugin.cc @@ -2,8 +2,8 @@ * This file is part of audacious-hotkey plugin for audacious * * Copyright (c) 2007 - 2008 Sascha Hlusiak - * Name: plugin.c - * Description: plugin.c + * Name: plugin.cc + * Description: plugin.cc * * Part of this code is from itouch-ctrl plugin. * Authors of itouch-ctrl are listed below: @@ -46,12 +46,13 @@ #include "api_hotkey.h" #include "grab.h" #include "gui.h" -#include "plugin.h" #ifdef BUILT_FROM_CMAKE #include "../../audacious-plugins_simpleAF/src/thirdparty/d_custom_logger.hpp" #endif +extern bool system_up_and_running; + class GlobalHotkeys : public GeneralPlugin { public: @@ -66,28 +67,24 @@ class GlobalHotkeys : public GeneralPlugin void cleanup() override; }; -EXPORT GlobalHotkeys aud_plugin_instance; - -#ifndef _WIN32 /* global vars */ -static -#else -PluginConfig plugin_cfg; -#endif - - const char GlobalHotkeys::about[] = N_( - "Global Hotkey Plugin\n" - "Control the player with global key combinations or multimedia " - "keys.\n\n" - "Copyright (C) 2007-2008 Sascha Hlusiak \n\n" - "Contributors include:\n" - "Copyright (C) 2006-2007 Vladimir Paskov \n" - "Copyright (C) 2000-2002 Ville Syrjälä ,\n" - " Bryn Davies ,\n" - " Jonathan A. Davis ,\n" - " Jeremy Tan "); - -PluginConfig * get_config() { return &plugin_cfg; } +EXPORT GlobalHotkeys aud_plugin_instance; +PluginConfig plugin_cfg_gtk_global_hk; + +const char GlobalHotkeys::about[] = + N_("Global Hotkey Plugin\n" + "Control the player with global key combinations or multimedia " + "keys.\n\n" + "Copyright (C) 2007-2008 Sascha Hlusiak \n\n" + "Contributors include:\n" + "Copyright (C) 2020 Domen Mori \n" + "Copyright (C) 2006-2007 Vladimir Paskov \n" + "Copyright (C) 2000-2002 Ville Syrjälä ,\n" + " Bryn Davies ,\n" + " Jonathan A. Davis ,\n" + " Jeremy Tan "); + +PluginConfig * get_config() { return &plugin_cfg_gtk_global_hk; } /* * plugin activated @@ -104,8 +101,9 @@ bool GlobalHotkeys::init() } #ifdef _WIN32 win_init(); -#endif +#else setup_filter(); +#endif load_config(); grab_keys(); return true; @@ -296,10 +294,9 @@ gboolean handle_keyevent(EVENT event) void load_defaults() { - AUDDBG("lHotkeyFlow:Entry, loading defaults."); HotkeyConfiguration * hotkey; - hotkey = &(plugin_cfg.first); + hotkey = &(plugin_cfg_gtk_global_hk.first); Hotkey::add_hotkey(&hotkey, OS_KEY_AudioPrev, 0, TYPE_KEY, EVENT_PREV_TRACK); @@ -329,7 +326,7 @@ void load_config() HotkeyConfiguration * hotkey; int i, max; - hotkey = &(plugin_cfg.first); + hotkey = &(plugin_cfg_gtk_global_hk.first); hotkey->next = nullptr; hotkey->key = 0; hotkey->mask = 0; @@ -378,7 +375,7 @@ void save_config() int max; HotkeyConfiguration * hotkey; - hotkey = &(plugin_cfg.first); + hotkey = &(plugin_cfg_gtk_global_hk.first); max = 0; while (hotkey) { @@ -411,14 +408,17 @@ void save_config() void GlobalHotkeys::cleanup() { +#ifdef _WIN32 + system_up_and_running = false; +#endif #ifdef BUILT_FROM_CMAKE + AUDWARN("Cleanup of globalHotkeys"); audlog::unsubscribe(&DCustomLogger::go); #endif - HotkeyConfiguration * hotkey; ungrab_keys(); release_filter(); - hotkey = &(plugin_cfg.first); + hotkey = &(plugin_cfg_gtk_global_hk.first); hotkey = hotkey->next; while (hotkey) { @@ -427,8 +427,8 @@ void GlobalHotkeys::cleanup() hotkey = hotkey->next; g_free(old); } - plugin_cfg.first.next = nullptr; - plugin_cfg.first.key = 0; - plugin_cfg.first.event = (EVENT)0; - plugin_cfg.first.mask = 0; + plugin_cfg_gtk_global_hk.first.next = nullptr; + plugin_cfg_gtk_global_hk.first.key = 0; + plugin_cfg_gtk_global_hk.first.event = (EVENT)0; + plugin_cfg_gtk_global_hk.first.mask = 0; } diff --git a/src/hotkey/plugin.h b/src/hotkey/plugin.h index 7b2c601318..d07b2ee317 100644 --- a/src/hotkey/plugin.h +++ b/src/hotkey/plugin.h @@ -1,3 +1,39 @@ +/* + * This file is part of audacious-hotkey plugin for audacious + * + * Copyright (c) 2007 - 2008 Sascha Hlusiak + * Name: plugin.h + * Description: plugin.h + * + * Part of this code is from itouch-ctrl plugin. + * Authors of itouch-ctrl are listed below: + * + * Copyright (c) 2006 - 2007 Vladimir Paskov + * + * Part of this code are from xmms-itouch plugin. + * Authors of xmms-itouch are listed below: + * + * Copyright (C) 2000-2002 Ville Syrjälä + * Bryn Davies + * Jonathan A. Davis + * Jeremy Tan + * + * audacious-hotkey is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * audacious-hotkey is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with audacious-hotkey; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + #ifndef _PLUGIN_H_INCLUDED_ #define _PLUGIN_H_INCLUDED_ @@ -71,7 +107,7 @@ PluginConfig * get_config(); gboolean handle_keyevent(EVENT event); #ifdef _WIN32 void win_init(); -extern PluginConfig plugin_cfg; #endif +extern PluginConfig plugin_cfg_gtk_global_hk; #endif diff --git a/src/hotkey/x_hotkey.cc b/src/hotkey/x_hotkey.cc index f1a4edd1e5..0517883208 100644 --- a/src/hotkey/x_hotkey.cc +++ b/src/hotkey/x_hotkey.cc @@ -1,3 +1,30 @@ +/* + * x_hotkey.cc + * Audacious + * + * Copyright (C) 2005-2020 Audacious team + * + * XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, + * Thomas Nilsson and 4Front Technologies + * Copyright (C) 1999-2003 Haavard Kvaalen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. +*/ + #include #include #include @@ -47,4 +74,25 @@ void Hotkey::key_to_string(int key, char ** out_keytext) { *out_keytext = g_strdup(XKeysymToString(keysym)); } +} + +char* Hotkey::create_human_readable_keytext(const char* const keytext, int key, int mask) +{ + static const constexpr unsigned int modifiers[] = { + HK_CONTROL_MASK, HK_SHIFT_MASK, HK_MOD1_ALT_MASK, HK_MOD2_MASK, + HK_MOD3_MASK, HK_MOD4_MASK, HK_MOD5_MASK}; + static const constexpr char * const modifier_string[] = { + "Control", "Shift", "Alt", "Mod2", "Mod3", "Super", "Mod5"}; + const char * strings[9]; + int i, j; + for (i = 0, j = 0; j < 7; j++) + { + if (mask & modifiers[j]) + strings[i++] = modifier_string[j]; + } + if (key != 0) + strings[i++] = keytext; + strings[i] = nullptr; + + return g_strjoinv(" + ", (char **)strings); } \ No newline at end of file diff --git a/src/hotkeyw32/Makefile b/src/hotkeyw32/Makefile index ef444054f3..95bdbcc2bb 100644 --- a/src/hotkeyw32/Makefile +++ b/src/hotkeyw32/Makefile @@ -1,6 +1,6 @@ PLUGIN = hotkeyw32${PLUGIN_SUFFIX} -SRCS = ../hotkey/gui.cc w32_grab.cc ../hotkey/grab.cc ../hotkey/plugin.cc w32_hotkey.cc ../hotkey/hotkey_api_common.cc +SRCS = ../hotkey/gui.cc ../hotkey/plugin.cc w32_hotkey.cc ../hotkey/hotkey_api_common.cc windows_window.cc include ../../buildsys.mk include ../../extra.mk diff --git a/src/hotkeyw32/w32_grab.cc b/src/hotkeyw32/w32_grab.cc deleted file mode 100644 index 4dc750ac75..0000000000 --- a/src/hotkeyw32/w32_grab.cc +++ /dev/null @@ -1,15 +0,0 @@ - - -#include "../hotkey/grab.h" - -#include - -#include -#include -#include -#include - -#include "../hotkey/plugin.h" - -void grab_keys() { AUDDBG("lHotkeyFlow:w_grab: grab_keys"); } -void ungrab_keys() { AUDDBG("lHotkeyFlow:w_grab: ungrab_keys"); } \ No newline at end of file diff --git a/src/hotkeyw32/w32_hotkey.cc b/src/hotkeyw32/w32_hotkey.cc index c220925691..526d1a6a8c 100644 --- a/src/hotkeyw32/w32_hotkey.cc +++ b/src/hotkeyw32/w32_hotkey.cc @@ -1,34 +1,68 @@ - +/* + * w32_hotkey.cc + * Audacious + * + * Copyright (C) 2005-2020 Audacious team + * + * XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, + * Thomas Nilsson and 4Front Technologies + * Copyright (C) 1999-2003 Haavard Kvaalen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. +*/ #include -#include #include +#include #include -#include -#include #include #include +#include #include -#include -#include +#include +#include #include "windows_key_str_map.h" +#include "windows_window.h" constexpr auto W_KEY_ID_PLAY = 18771; constexpr auto W_KEY_ID_PREV = 18772; constexpr auto W_KEY_ID_NEXT = 18773; constexpr auto W_FIRST_GLOBAL_KEY_ID = 18774; +bool system_up_and_running{false}; + +/** + * Handle to window that has thumbbar buttons associated. Nullptr if it is not + * on display. + */ +WindowsWindow message_receiving_window{ + nullptr, {}, {}, AudaciousWindowKind::UNKNOWN}; + template std::string VirtualKeyCodeToStringMethod2(T virtualKey) { - WCHAR name[128]; + wchar_t name[128]; static auto key_layout = GetKeyboardLayout(0); UINT scanCode = MapVirtualKeyEx(virtualKey, MAPVK_VK_TO_VSC, key_layout); LONG lParamValue = (scanCode << 16); - int result = GetKeyNameTextW(lParamValue, name, 1024); + int result = GetKeyNameTextW(lParamValue, name, sizeof name); if (result > 0) { auto * windows_cmd = reinterpret_cast( @@ -44,11 +78,12 @@ std::string VirtualKeyCodeToStringMethod2(T virtualKey) } } +void grab_keys_onto_window(); + void Hotkey::add_hotkey(HotkeyConfiguration ** pphotkey, Hotkey::OS_KeySym keysym, int mask, int type, EVENT event) { - AUDDBG("lHotkeyFlow:Win call."); HotkeyConfiguration * photkey; if (keysym == 0) return; @@ -75,7 +110,7 @@ void Hotkey::add_hotkey(HotkeyConfiguration ** pphotkey, void register_global_keys(HWND handle) { - auto * hotkey = &(plugin_cfg.first); + auto * hotkey = &(plugin_cfg_gtk_global_hk.first); auto _id = W_FIRST_GLOBAL_KEY_ID; while (hotkey) { @@ -93,50 +128,125 @@ void register_global_keys(HWND handle) // ptr_first_element[loc] = 0; //} -HRESULT AddThumbarButtons(HWND hwnd) -{ - // Define an array of two buttons. These buttons provide images through an - // image list and also provide tooltips. - THUMBBUTTONMASK dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS; - - /* - THUMBBUTTONMASK dwMask; - UINT iId; - UINT iBitmap; - HICON hIcon; - WCHAR szTip[260]; - THUMBBUTTONFLAGS dwFlags; - */ - - THUMBBUTTON btn[]{ - {dwMask, W_KEY_ID_PREV, 0, nullptr, L"Previous song", THBF_ENABLED}, - {dwMask, W_KEY_ID_PLAY, 0, nullptr, L"Play/pause", THBF_ENABLED}, - {dwMask, W_KEY_ID_NEXT, 0, nullptr, L"Next song", THBF_ENABLED}}; - - ITaskbarList3 * ptbl; - HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, - IID_PPV_ARGS(&ptbl)); +//HRESULT AddThumbarButtons(HWND hwnd) +//{ +// // Define an array of two buttons. These buttons provide images through an +// // image list and also provide tooltips. +// THUMBBUTTONMASK dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS; +// +// /* +// THUMBBUTTONMASK dwMask; +// UINT iId; +// UINT iBitmap; +// HICON hIcon; +// WCHAR szTip[260]; +// THUMBBUTTONFLAGS dwFlags; +// */ +// +// THUMBBUTTON btn[]{ +// {dwMask, W_KEY_ID_PREV, 0, nullptr, L"Previous song", THBF_ENABLED}, +// {dwMask, W_KEY_ID_PLAY, 0, nullptr, L"Play/pause", THBF_ENABLED}, +// {dwMask, W_KEY_ID_NEXT, 0, nullptr, L"Next song", THBF_ENABLED}}; +// +// ITaskbarList3 * ptbl; +// HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, +// IID_PPV_ARGS(&ptbl)); +// +// if (SUCCEEDED(hr)) +// { +// // Declare the image list that contains the button images. +// // hr = ptbl->ThumbBarSetImageList(hwnd, himl); +// +// if (SUCCEEDED(hr)) +// { +// // Attach the toolbar to the thumbnail. +// hr = ptbl->ThumbBarAddButtons(hwnd, ARRAYSIZE(btn), btn); +// } +// ptbl->Release(); +// } +// return hr; +//} - if (SUCCEEDED(hr)) +GdkFilterReturn w32_events_filter_first_everything(GdkXEvent * gdk_xevent, + GdkEvent * event, + gpointer user_data) +{ + auto msg = reinterpret_cast(gdk_xevent); + if (!msg->hwnd) { - // Declare the image list that contains the button images. - // hr = ptbl->ThumbBarSetImageList(hwnd, himl); - - if (SUCCEEDED(hr)) + AUDWARN("We have event but hwnd is null. This doesn't make sense."); + return GDK_FILTER_CONTINUE; + } + // log_win_msg(msg->message); + if (msg->message == WM_SHOWWINDOW) + { + if (msg->wParam == TRUE) { - // Attach the toolbar to the thumbnail. - hr = ptbl->ThumbBarAddButtons(hwnd, ARRAYSIZE(btn), btn); + auto event_window = WindowsWindow::get_window_data(msg->hwnd); + AUDDBG("(CommingUp)TRUE %s; %s", + stringify_win_evt(msg->message).c_str(), + (static_cast(event_window)).c_str()); + if (event_window.is_main_window(true)) + { + event_window. + WindowsWindow::main_window_hidden_ = false; + AUDDBG( + "TRANSFER EventReceivingWindow from %s to mainwindow HWND " + "%p", + static_cast(message_receiving_window).c_str(), + event_window.handle()); + ungrab_keys(); + message_receiving_window = std::move(event_window); + grab_keys_onto_window(); + } } - ptbl->Release(); + // else + // { + // // leaving us. + // AUDDBG("(GettingDown)FALSE %s; %s", + // stringify_win_evt(msg->message).c_str(), + // (static_cast(event_window)).c_str()); + // } } - return hr; + // else if (msg->message == WM_CLOSE) + // { + // auto event_window = WindowsWindow::get_window_data(msg->hwnd); + // AUDDBG("%s: ; %s", stringify_win_evt(msg->message).c_str(), + // (static_cast(event_window)).c_str()); + // } + // else if (msg->message == WM_CREATE) + // { + // auto event_window = WindowsWindow::get_window_data(msg->hwnd); + // AUDDBG("%s: ; %s", stringify_win_evt(msg->message).c_str(), + // (static_cast(event_window)).c_str()); + // } + // else if (msg->message == WM_DESTROY) + // { + // auto event_window = WindowsWindow::get_window_data(msg->hwnd); + // AUDDBG("%s: ; %s", stringify_win_evt(msg->message).c_str(), + // (static_cast(event_window)).c_str()); + // } + return GDK_FILTER_CONTINUE; } -GdkFilterReturn buttons_evts_filter(GdkXEvent * gdk_xevent, GdkEvent * event, - gpointer user_data) +GdkFilterReturn w32_evts_filter(GdkXEvent * gdk_xevent, GdkEvent * event, + gpointer user_data) { auto msg = reinterpret_cast(gdk_xevent); - if (msg->message == WM_COMMAND) + // log_win_msg(msg->message); + if (msg->message == WM_SHOWWINDOW) + { + if (msg->wParam != TRUE) + { + AUDDBG("MainWindow is getting hidden. We need to recreate the " + "hooks.\n TRANSFER EventReceivingWindow from %s", + static_cast(message_receiving_window).c_str()); + WindowsWindow::main_window_hidden_ = true; + ungrab_keys(); + grab_keys(); + } + } + else if (msg->message == WM_COMMAND) { auto buttonId = static_cast(msg->wParam & 0xFFFF); AUDDBG("Clicked button with ID: %d", buttonId); @@ -150,73 +260,88 @@ GdkFilterReturn buttons_evts_filter(GdkXEvent * gdk_xevent, GdkEvent * event, break; case W_KEY_ID_PREV: handle_keyevent(EVENT_PREV_TRACK); + break; } return GDK_FILTER_REMOVE; } - if (msg->message == WM_HOTKEY) + else if (msg->message == WM_HOTKEY) { - auto k_id = static_cast(msg->wParam & 0xFFFF); - AUDDBG("lHotkeyFlow:Global hotkey: %d", k_id); + auto k_id = LOWORD(msg->wParam); + AUDDBG("Global hotkey: %du", k_id); // Max 20 HKs if (k_id >= W_FIRST_GLOBAL_KEY_ID && k_id < W_FIRST_GLOBAL_KEY_ID + 20) { auto idx = k_id - W_FIRST_GLOBAL_KEY_ID; - auto * config = &plugin_cfg.first; + auto * config = &plugin_cfg_gtk_global_hk.first; while (idx--) { config = config->next; } - handle_keyevent(config->event); + if (handle_keyevent(config->event)) + { + return GDK_FILTER_REMOVE; + } } } return GDK_FILTER_CONTINUE; } -struct EnumWindowsCallbackArgs -{ - explicit EnumWindowsCallbackArgs(DWORD p) : pid(p) {} - const DWORD pid; - std::vector handles; -}; - -static BOOL CALLBACK EnumWindowsCallback(HWND hnd, LPARAM lParam) +void register_hotkeys_with_available_window() { - // Get pointer to created callback object for storing data. - auto * args = reinterpret_cast(lParam); - // Callback result are all windows (not only my program). I filter by PID / - // thread ID. - DWORD windowPID; - GetWindowThreadProcessId(hnd, &windowPID); - // Compare to the one we have stored in our callbaack structure. - if (windowPID == args->pid) + assert(static_cast(message_receiving_window)); + auto * gdkwin = message_receiving_window.gdk_window(); + if (!gdkwin) { - args->handles.push_back(hnd); + AUDINFO("HWND doesn't have associated gdk window. Cannot setup global " + "hotkeys."); + return; } - - return TRUE; + gdk_window_add_filter(gdkwin, w32_evts_filter, nullptr); + register_global_keys(message_receiving_window.handle()); } -std::vector getToplevelWindows() +void release_filter() { - // Create object that will hold a result. - EnumWindowsCallbackArgs args(GetCurrentProcessId()); - // AUDERR("Testing getlasterror: %ld\n.", GetLastError()); - // Call EnumWindows and pass pointer to function and created callback - // structure. - if (EnumWindows(&EnumWindowsCallback, (LPARAM)&args) == FALSE) + if (!message_receiving_window) { - // If the call fails, return empty vector - AUDERR("WinApiError (code %ld). Cannot get windows, hotkey plugin " - "won't work.\n", - GetLastError()); - return std::vector(); + return; } - // Otherwise, callback function filled the struct. Return important data. - // Test: GetActiveWindow - args.handles.push_back(GetActiveWindow()); - args.handles.push_back(GetForegroundWindow()); - return args.handles; + gdk_window_remove_filter(message_receiving_window.gdk_window(), + w32_evts_filter, nullptr); + message_receiving_window = nullptr; } +// +// void main_window_created_from_statusbar( +// MainWindowSearchFilterData * const passed_data, +// WindowsWindow & created_main_window) +//{ +// // When window fully shows, must add windows buttons. +// gdk_window_remove_filter( +// reinterpret_cast(passed_data->window_), +// reinterpret_cast(passed_data->function_ptr_), +// passed_data); +// ungrab_keys(); +// release_filter(); +// delete passed_data; +//} +// +// GdkFilterReturn main_window_missing_filter(GdkXEvent * gdk_xevent, +// GdkEvent * event, gpointer +// user_data) +//{ +// auto msg = reinterpret_cast(gdk_xevent); +// if (msg->message == WM_SHOWWINDOW && msg->wParam) +// { +// auto win_data = WindowsWindow::get_window_data(msg->hwnd); +// if (win_data.is_main_window()) +// { +// main_window_created_from_statusbar( +// reinterpret_cast(user_data), +// win_data); +// } +// } +// return GDK_FILTER_CONTINUE; +//} /** * GSourceFunc: @@ -231,50 +356,15 @@ std::vector getToplevelWindows() */ gboolean window_created_callback(gpointer user_data) { - - AUDDBG("lHotkeyFlow:Window created. Do real stuff."); - auto wins = getToplevelWindows(); - AUDDBG("lHotkeyFlow:windows: %zu", wins.size()); - for (auto win : wins) - { - wchar_t className[311]; - GetClassNameW(win, className, _countof(className)); - auto s_cn = reinterpret_cast( - g_utf16_to_utf8(reinterpret_cast(className), -1, - nullptr, nullptr, nullptr)); - - GetWindowTextW(win, className, _countof(className)); - auto s_cn2 = reinterpret_cast( - g_utf16_to_utf8(reinterpret_cast(className), -1, - nullptr, nullptr, nullptr)); - if (s_cn) - { - AUDDBG("lHotkeyFlow:WIN: %s%s", s_cn, - ([s_cn2]() { - std::string returning{}; - if (s_cn2) - { - returning = std::string(" titled: ") + s_cn2; - g_free(s_cn2); - } - return returning; - }()) - .c_str()); - g_free(s_cn); - } - } - auto the_hwnd = wins.back(); - // AddThumbarButtons(the_hwnd); Disabled for now ... first get hotkeys - // perfectly stable - auto gdkwin = gdk_win32_handle_table_lookup(the_hwnd); - gdk_window_add_filter((GdkWindow *)gdkwin, buttons_evts_filter, nullptr); - register_global_keys(the_hwnd); - return false; + AUDDBG("Window created. Do real stuff."); + system_up_and_running = true; + gdk_window_add_filter(nullptr, w32_events_filter_first_everything, nullptr); + grab_keys(); + return G_SOURCE_REMOVE; } void win_init() { - AUDDBG("lHotkeyFlow:Win .. important call."); g_idle_add(&window_created_callback, nullptr); } @@ -324,4 +414,73 @@ void Hotkey::key_to_string(int key, char ** out_keytext) } } *out_keytext = g_strdup(WIN_VK_NAMES[key]); +} + +char * Hotkey::create_human_readable_keytext(const char * const keytext, + int key, int mask) +{ + const auto w_mask = static_cast(mask); + std::ostringstream produced; + // "Control", "Shift", "Alt", "Win" + if (w_mask & static_cast(MOD_CONTROL)) + { + produced << "Control + "; + } + if (w_mask & static_cast(MOD_SHIFT)) + { + produced << "Shift + "; + } + if (w_mask & static_cast(MOD_ALT)) + { + produced << "Alt + "; + } + if (w_mask & static_cast(MOD_WIN)) + { + produced << "Win + "; + } + produced << keytext; + + AUDDBG(produced.str().c_str()); + return g_strdup(produced.str().c_str()); +} +void grab_keys_onto_window() +{ + AUDDBG("Will hook together the window of kind %s\n :%s", + message_receiving_window.kind_string(), + static_cast(message_receiving_window).c_str()); + if (message_receiving_window.kind() == AudaciousWindowKind::NONE || + message_receiving_window.kind() == AudaciousWindowKind::UNKNOWN) + { + AUDERR("Win API did not find the window to receive messages. Global " + "hotkeys are disabled!"); + message_receiving_window = nullptr; + return; + } + register_hotkeys_with_available_window(); +} +void grab_keys() +{ + if (!system_up_and_running) + { + return; + } + AUDDBG("Grabbing ..."); + + message_receiving_window = WindowsWindow::find_message_receiver_window(); + grab_keys_onto_window(); +} +void ungrab_keys() +{ + AUDDBG("Releasing ..."); + if (message_receiving_window) + { + auto * hotkey = &(plugin_cfg_gtk_global_hk.first); + auto _id = W_FIRST_GLOBAL_KEY_ID; + while (hotkey) + { + UnregisterHotKey(message_receiving_window.handle(), _id++); + hotkey = hotkey->next; + } + } + release_filter(); } \ No newline at end of file diff --git a/src/hotkeyw32/windows_key_str_map.h b/src/hotkeyw32/windows_key_str_map.h index ccb7ae4648..63cfd124a7 100644 --- a/src/hotkeyw32/windows_key_str_map.h +++ b/src/hotkeyw32/windows_key_str_map.h @@ -1,3 +1,30 @@ +/* + * windows_key_str_map.h + * Audacious + * + * Copyright (C) 2005-2020 Audacious team + * + * XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, + * Thomas Nilsson and 4Front Technologies + * Copyright (C) 1999-2003 Haavard Kvaalen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. +*/ + #ifndef AUDACIOUS_PLUGINS_WINDOWS_KEY_STRINGS_HPP #define AUDACIOUS_PLUGINS_WINDOWS_KEY_STRINGS_HPP diff --git a/src/hotkeyw32/windows_window.cc b/src/hotkeyw32/windows_window.cc new file mode 100644 index 0000000000..f584e3b433 --- /dev/null +++ b/src/hotkeyw32/windows_window.cc @@ -0,0 +1,316 @@ +/* + * windows_window.cc + * Audacious + * + * Copyright (C) 2005-2020 Audacious team + * + * XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, + * Thomas Nilsson and 4Front Technologies + * Copyright (C) 1999-2003 Haavard Kvaalen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. +*/ + +#include "windows_window.h" + +#include +#include +#include +#include +#include +#include + +class Utf16CharArrConverter +{ + gchar * converted{nullptr}; + +public: + Utf16CharArrConverter(const wchar_t * const input_w_str) + : converted(reinterpret_cast( + g_utf16_to_utf8(reinterpret_cast(input_w_str), + -1, nullptr, nullptr, nullptr))) + { + } + ~Utf16CharArrConverter() + { + if (converted) + { + g_free(converted); + } + }; + operator std::string() + { // NOLINT(google-explicit-constructor) + return std::string(converted); + } +}; + +template +std::string to_hex_string(T integer) +{ + std::ostringstream os; + os << "0x" << std::setw(4) << std::setfill('0') << std::hex << integer; + return os.str(); +} + +std::string print_wins(const std::vector & wins) +{ + std::string printer; + for (auto & w : wins) + { + printer.append("\n ").append(static_cast(w)); + } + return printer; +} + +WindowsWindow::WindowsWindow(HWND handle, std::string className, + std::string winHeader, AudaciousWindowKind kind) + : handle_(handle), class_name_(std::move(className)), + win_header_(std::move(winHeader)), kind_(kind) +{ +} +std::string WindowsWindow::translated_title() +{ + // get "%s - " + std::string org = N_("%s - Audacious"); + // erase %s + org.erase(0, 2); + return org; +} +bool WindowsWindow::is_main_window(bool allow_hidden) const +{ + if (main_window_hidden_ && !allow_hidden) + return false; + bool returning = + (class_name_ == "gdkWindowToplevel" && [](const std::string & title) { + return title == N_("Audacious") || + title.find(translated_title()) != std::string::npos || + title == N_("Buffering ..."); // msgid "%s - Audacious" + }(win_header_)); + if (returning) + { + kind_ = AudaciousWindowKind::MAIN_WINDOW; + } + return returning; +} +WindowsWindow::operator std::string() const +{ + if (!handle_) + { + return "INVALID_WINDOW"; + } + std::string printer; + printer.append(std::to_string(reinterpret_cast(handle_))) + .append("|") + .append(to_hex_string(handle_)) + .append("(gdk:") + .append(std::to_string(reinterpret_cast(gdk_window()))) + .append("|") + .append(to_hex_string(gdk_window())) + .append(") ") + .append(class_name_) + .append(": ") + .append(win_header_); + return printer; +} +WindowsWindow WindowsWindow::get_window_data(HWND pHwnd) +{ + wchar_t char_buf[311]; + auto num_char = GetClassNameW(pHwnd, char_buf, _countof(char_buf)); + if (!num_char) + { + AUDDBG("WinApiError (code %ld): cannot get ClassName for %p.\n", + GetLastError(), pHwnd); + return {}; + } + std::string w_class_name = Utf16CharArrConverter(char_buf); + num_char = GetWindowTextW(pHwnd, char_buf, _countof(char_buf)); + if (!num_char) + { + AUDINFO("WinApiError (code %ld) getting WindowHeader. No header " + "for %p. Ignoring this window.\n", + GetLastError(), pHwnd); + char_buf[0] = 0; + } + return {pHwnd, std::move(w_class_name), + char_buf[0] ? Utf16CharArrConverter(char_buf) + : std::string{"[NO_TITLE]"}, + AudaciousWindowKind::UNKNOWN}; +} + +struct EnumWindowsCallbackArgs +{ + explicit EnumWindowsCallbackArgs(DWORD p) : pid(p) {} + const DWORD pid; + std::vector handles; + + void add_window(HWND pHwnd) + { + handles.emplace_back(WindowsWindow::get_window_data(pHwnd)); + } +}; + +static BOOL CALLBACK EnumWindowsCallback(HWND hnd, LPARAM lParam) +{ + // Get pointer to created callback object for storing data. + auto * args = reinterpret_cast(lParam); + // Callback result are all windows (not only my program). I filter by PID / + // thread ID. + DWORD windowPID; + GetWindowThreadProcessId(hnd, &windowPID); + // Compare to the one we have stored in our callbaack structure. + if (windowPID == args->pid) + { + args->add_window(hnd); + } + return TRUE; +} + +std::vector get_this_app_windows() +{ + // Create object that will hold a result. + EnumWindowsCallbackArgs args(GetCurrentProcessId()); + // AUDERR("Testing getlasterror: %ld\n.", GetLastError()); + // Call EnumWindows and pass pointer to function and created callback + // structure. + if (EnumWindows(&EnumWindowsCallback, (LPARAM)&args) == FALSE) + { + // If the call fails, return empty vector + AUDERR("WinApiError (code %ld). Cannot get windows, hotkey plugin " + "won't work.\n", + GetLastError()); + return std::vector{}; + } +#ifndef NDEBUG + AUDDBG("Aud has %zu windows: %s", args.handles.size(), + print_wins(args.handles).c_str()); +#endif + return std::move(args.handles); +} +WindowsWindow WindowsWindow::find_message_receiver_window() +{ + auto ws = get_this_app_windows(); + auto main_win = std::find_if(ws.begin(), ws.end(), [](WindowsWindow & itm) { + return itm.is_main_window(); + }); + if (main_win != ws.end()) + { + main_win->kind_ = AudaciousWindowKind::MAIN_WINDOW; + return std::move(*main_win); + } + main_win = + std::find_if(ws.begin(), ws.end(), [](const WindowsWindow & itm) { + return itm.gdk_window() != nullptr; + }); + if (main_win != ws.end()) + { + main_win->kind_ = + AudaciousWindowKind::TASKBAR_WITH_WINHANDLE_AND_GDKHANDLE; + return std::move(*main_win); + } + main_win = + std::find_if(ws.begin(), ws.end(), [](const WindowsWindow & itm) { + return itm.class_name_ == "gtkstatusicon-observer"; + }); + if (main_win == ws.end()) + { + AUDDBG("No proper window found. Giving up."); + return {nullptr, {}, {}, AudaciousWindowKind::NONE}; + } + main_win->kind_ = AudaciousWindowKind::GTKSTATUSICON_OBSERVER; + return std::move(*main_win); +} +WindowsWindow::operator bool() const { return handle_; } +GdkWindow * WindowsWindow::gdk_window() const +{ + if (!gdk_window_) + { + gdk_window_ = reinterpret_cast( + gdk_win32_handle_table_lookup(handle_)); + } + return gdk_window_; +} +void WindowsWindow::unref() +{ + handle_ = nullptr; + gdk_window_ = nullptr; +} + +#define ENUM_KIND_CASE(item) \ + case item: \ + return #item; + +const char * WindowsWindow::kind_string() +{ + switch (kind_) + { + ENUM_KIND_CASE(AudaciousWindowKind::MAIN_WINDOW) + ENUM_KIND_CASE(AudaciousWindowKind::UNKNOWN) + ENUM_KIND_CASE(AudaciousWindowKind::NONE) + ENUM_KIND_CASE(AudaciousWindowKind::GTKSTATUSICON_OBSERVER) + ENUM_KIND_CASE( + AudaciousWindowKind::TASKBAR_WITH_WINHANDLE_AND_GDKHANDLE) + } + return "bad WindowsWindow ; unknown"; +} + +std::string stringify_win_evt(UINT id) +{ + switch (id) + { + ENUM_KIND_CASE(WM_DESTROY) + ENUM_KIND_CASE(WM_CREATE) + ENUM_KIND_CASE(WM_ACTIVATE) + ENUM_KIND_CASE(WM_ENABLE) + ENUM_KIND_CASE(WM_SHOWWINDOW) + ENUM_KIND_CASE(WM_WINDOWPOSCHANGING) + ENUM_KIND_CASE(WM_WINDOWPOSCHANGED) + ENUM_KIND_CASE(WM_NCACTIVATE) + ENUM_KIND_CASE(WM_NCPAINT) + ENUM_KIND_CASE(WM_NCCREATE) + ENUM_KIND_CASE(WM_ACTIVATEAPP) + ENUM_KIND_CASE(WM_KILLFOCUS) + ENUM_KIND_CASE(WM_SETFOCUS) + ENUM_KIND_CASE(WM_IME_SETCONTEXT) + ENUM_KIND_CASE(WM_IME_NOTIFY) + ENUM_KIND_CASE(WM_GETICON) + ENUM_KIND_CASE(WM_PAINT) + ENUM_KIND_CASE(WM_SETCURSOR) + ENUM_KIND_CASE(WM_MOUSEMOVE) + ENUM_KIND_CASE(WM_NCMOUSEMOVE) + ENUM_KIND_CASE(WM_MOUSEACTIVATE) + ENUM_KIND_CASE(WM_NCLBUTTONDOWN) + ENUM_KIND_CASE(WM_CAPTURECHANGED) + ENUM_KIND_CASE(WM_SYSCOMMAND) + ENUM_KIND_CASE(WM_CLOSE) + ENUM_KIND_CASE(WM_MOVING) + ENUM_KIND_CASE(WM_ERASEBKGND) + ENUM_KIND_CASE(WM_EXITMENULOOP) + ENUM_KIND_CASE(WM_NCMOUSELEAVE) + ENUM_KIND_CASE(WM_NCHITTEST) + ENUM_KIND_CASE(WM_EXITSIZEMOVE) + ENUM_KIND_CASE(WM_ENTERSIZEMOVE) + ENUM_KIND_CASE(WM_MOUSELEAVE) + ENUM_KIND_CASE(WM_PARENTNOTIFY) + ENUM_KIND_CASE(WM_NCCALCSIZE) + ENUM_KIND_CASE(WM_GETMINMAXINFO) + ENUM_KIND_CASE(WM_QUERYOPEN) + default: + return "Unknown msg: " + to_hex_string(id); + } +} + +bool WindowsWindow::main_window_hidden_{false}; \ No newline at end of file diff --git a/src/hotkeyw32/windows_window.h b/src/hotkeyw32/windows_window.h new file mode 100644 index 0000000000..bc32c378f7 --- /dev/null +++ b/src/hotkeyw32/windows_window.h @@ -0,0 +1,105 @@ +/* + * windows_window.h + * Audacious + * + * Copyright (C) 2005-2020 Audacious team + * + * XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, + * Thomas Nilsson and 4Front Technologies + * Copyright (C) 1999-2003 Haavard Kvaalen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. +*/ + +#ifndef _AUD_PLUGINS_HOTKEYW32_WINDOWS_WINDOW_H_INCLUDED_ +#define _AUD_PLUGINS_HOTKEYW32_WINDOWS_WINDOW_H_INCLUDED_ + +#include +#include +#include + +enum class AudaciousWindowKind +{ + NONE, + MAIN_WINDOW, + TASKBAR_WITH_WINHANDLE_AND_GDKHANDLE, + GTKSTATUSICON_OBSERVER, + UNKNOWN +}; + +struct WindowsWindow +{ + static bool main_window_hidden_; + WindowsWindow() = default; + ~WindowsWindow() = default; + WindowsWindow(const WindowsWindow & right) = delete; + WindowsWindow & operator=(const WindowsWindow & right) = delete; + WindowsWindow & operator=(WindowsWindow && right) = default; + WindowsWindow(WindowsWindow && right) = default; + + WindowsWindow(HWND handle, std::string className, std::string winHeader, AudaciousWindowKind kind); + static std::string translated_title(); + bool is_main_window(bool allow_hidden = false) const; + explicit operator std::string() const; + static WindowsWindow get_window_data(HWND pHwnd); + static WindowsWindow find_message_receiver_window(); + + operator bool() const; // NOLINT(google-explicit-constructor) + // clang-format off + void unref(); + WindowsWindow& operator=(std::nullptr_t dummy) { unref(); return *this; } + // clang-format on + + HWND handle() const { return handle_; } + const std::string & class_name() const { return class_name_; } + const std::string & win_header() const { return win_header_; } + AudaciousWindowKind kind() const { return kind_; } + GdkWindow * gdk_window() const; + + const char * kind_string(); + +private: + HWND handle_{}; + std::string class_name_{}; + std::string win_header_{}; + mutable AudaciousWindowKind kind_{}; + mutable GdkWindow * gdk_window_{}; +}; + +struct MainWindowSearchFilterData +{ + gpointer window_; + void * function_ptr_; + + MainWindowSearchFilterData(gpointer window, void * functionPtr) + : window_(window), function_ptr_(functionPtr) + { + } + + MainWindowSearchFilterData(const MainWindowSearchFilterData &) = delete; + MainWindowSearchFilterData(MainWindowSearchFilterData &&) = delete; + MainWindowSearchFilterData & + operator=(const MainWindowSearchFilterData &) = delete; + MainWindowSearchFilterData & + operator=(MainWindowSearchFilterData &&) = delete; + ~MainWindowSearchFilterData() = default; +}; + +std::vector get_this_app_windows(); +std::string stringify_win_evt(UINT id); + +#endif \ No newline at end of file From 82e9bacc824d90bf5dbc2a6f54c5aaffcdf6163a Mon Sep 17 00:00:00 2001 From: Domen Mori Date: Sun, 13 Dec 2020 16:46:42 +0100 Subject: [PATCH 4/4] Clang format, new standards --- src/hotkey/api_hotkey.h | 5 +- src/hotkey/grab.h | 2 +- src/hotkey/gui.cc | 3 +- src/hotkey/gui.h | 2 +- src/hotkey/hotkey_api_common.cc | 2 +- src/hotkey/plugin.cc | 19 ---- src/hotkey/x_hotkey.cc | 5 +- src/hotkeyw32/w32_hotkey.cc | 132 +--------------------------- src/hotkeyw32/windows_key_str_map.h | 2 +- src/hotkeyw32/windows_window.cc | 2 +- src/hotkeyw32/windows_window.h | 5 +- 11 files changed, 20 insertions(+), 159 deletions(-) diff --git a/src/hotkey/api_hotkey.h b/src/hotkey/api_hotkey.h index 0d2e563ab3..8caa68f4ef 100644 --- a/src/hotkey/api_hotkey.h +++ b/src/hotkey/api_hotkey.h @@ -23,7 +23,7 @@ * * The Audacious team does not consider modular code linking to * Audacious or using our public API to be a derived work. -*/ + */ #ifndef _X_HOTKEY_H_INCLUDED #define _X_HOTKEY_H_INCLUDED @@ -59,7 +59,8 @@ class Hotkey static void add_hotkey(HotkeyConfiguration ** pphotkey, OS_KeySym keysym, int mask, int type, EVENT event); static void key_to_string(int key, char ** out_keytext); - static char* create_human_readable_keytext(const char* const keytext, int key, int mask); + static char * create_human_readable_keytext(const char * const keytext, + int key, int mask); }; #ifndef _WIN32 diff --git a/src/hotkey/grab.h b/src/hotkey/grab.h index c416345aef..8860017902 100644 --- a/src/hotkey/grab.h +++ b/src/hotkey/grab.h @@ -23,7 +23,7 @@ * * The Audacious team does not consider modular code linking to * Audacious or using our public API to be a derived work. -*/ + */ #ifndef _GRAB_H_INCLUDED_ #define _GRAB_H_INCLUDED_ diff --git a/src/hotkey/gui.cc b/src/hotkey/gui.cc index 362ce2637f..342c5bc59e 100644 --- a/src/hotkey/gui.cc +++ b/src/hotkey/gui.cc @@ -129,7 +129,8 @@ static gboolean on_entry_key_press_event(GtkWidget * widget, Hotkey::set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod, TYPE_KEY); - // Returning TRUE indicates that the event has been handled, and that it should not propagate further. + // Returning TRUE indicates that the event has been handled, and that it + // should not propagate further. return true; } diff --git a/src/hotkey/gui.h b/src/hotkey/gui.h index 8dcced0936..3239d4a24f 100644 --- a/src/hotkey/gui.h +++ b/src/hotkey/gui.h @@ -23,7 +23,7 @@ * * The Audacious team does not consider modular code linking to * Audacious or using our public API to be a derived work. -*/ + */ #ifndef _GUI_H_INCLUDED_ #define _GUI_H_INCLUDED_ diff --git a/src/hotkey/hotkey_api_common.cc b/src/hotkey/hotkey_api_common.cc index 338a8e8911..f077dd14bb 100644 --- a/src/hotkey/hotkey_api_common.cc +++ b/src/hotkey/hotkey_api_common.cc @@ -23,7 +23,7 @@ * * The Audacious team does not consider modular code linking to * Audacious or using our public API to be a derived work. -*/ + */ #include "api_hotkey.h" #include diff --git a/src/hotkey/plugin.cc b/src/hotkey/plugin.cc index f6e91f64fd..4ac42faa44 100644 --- a/src/hotkey/plugin.cc +++ b/src/hotkey/plugin.cc @@ -47,10 +47,6 @@ #include "grab.h" #include "gui.h" -#ifdef BUILT_FROM_CMAKE -#include "../../audacious-plugins_simpleAF/src/thirdparty/d_custom_logger.hpp" -#endif - extern bool system_up_and_running; class GlobalHotkeys : public GeneralPlugin @@ -91,9 +87,6 @@ PluginConfig * get_config() { return &plugin_cfg_gtk_global_hk; } */ bool GlobalHotkeys::init() { -#ifdef BUILT_FROM_CMAKE - audlog::subscribe(&DCustomLogger::go, audlog::Level::Debug); -#endif if (!gtk_init_check(nullptr, nullptr)) { AUDERR("GTK+ initialization failed.\n"); @@ -305,19 +298,11 @@ void load_defaults() Hotkey::add_hotkey(&hotkey, OS_KEY_AudioStop, 0, TYPE_KEY, EVENT_STOP); Hotkey::add_hotkey(&hotkey, OS_KEY_AudioNext, 0, TYPE_KEY, EVENT_NEXT_TRACK); - - /* add_hotkey(&hotkey, OS_KEY_AudioRewind, 0, TYPE_KEY, EVENT_BACKWARD); - */ - Hotkey::add_hotkey(&hotkey, OS_KEY_AudioMute, 0, TYPE_KEY, EVENT_MUTE); Hotkey::add_hotkey(&hotkey, OS_KEY_AudioRaiseVolume, 0, TYPE_KEY, EVENT_VOL_UP); Hotkey::add_hotkey(&hotkey, OS_KEY_AudioLowerVolume, 0, TYPE_KEY, EVENT_VOL_DOWN); - - /* add_hotkey(&hotkey, OS_KEY_AudioMedia, 0, TYPE_KEY, - EVENT_JUMP_TO_FILE); add_hotkey(&hotkey, XF86XK_Music, 0, TYPE_KEY, - EVENT_TOGGLE_WIN); */ } /* load plugin configuration */ @@ -410,10 +395,6 @@ void GlobalHotkeys::cleanup() { #ifdef _WIN32 system_up_and_running = false; -#endif -#ifdef BUILT_FROM_CMAKE - AUDWARN("Cleanup of globalHotkeys"); - audlog::unsubscribe(&DCustomLogger::go); #endif HotkeyConfiguration * hotkey; ungrab_keys(); diff --git a/src/hotkey/x_hotkey.cc b/src/hotkey/x_hotkey.cc index 0517883208..1b14904395 100644 --- a/src/hotkey/x_hotkey.cc +++ b/src/hotkey/x_hotkey.cc @@ -23,7 +23,7 @@ * * The Audacious team does not consider modular code linking to * Audacious or using our public API to be a derived work. -*/ + */ #include #include @@ -76,7 +76,8 @@ void Hotkey::key_to_string(int key, char ** out_keytext) } } -char* Hotkey::create_human_readable_keytext(const char* const keytext, int key, int mask) +char * Hotkey::create_human_readable_keytext(const char * const keytext, + int key, int mask) { static const constexpr unsigned int modifiers[] = { HK_CONTROL_MASK, HK_SHIFT_MASK, HK_MOD1_ALT_MASK, HK_MOD2_MASK, diff --git a/src/hotkeyw32/w32_hotkey.cc b/src/hotkeyw32/w32_hotkey.cc index 526d1a6a8c..666e9f6a84 100644 --- a/src/hotkeyw32/w32_hotkey.cc +++ b/src/hotkeyw32/w32_hotkey.cc @@ -23,7 +23,7 @@ * * The Audacious team does not consider modular code linking to * Audacious or using our public API to be a derived work. -*/ + */ #include @@ -92,9 +92,6 @@ void Hotkey::add_hotkey(HotkeyConfiguration ** pphotkey, photkey = *pphotkey; if (photkey == nullptr) return; - // keycode = - // XKeysymToKeycode(GDK_DISPLAY_XDISPLAY(gdk_display_get_default()), - // keysym); if (keycode == 0) return; if (photkey->key) { photkey->next = g_new(HotkeyConfiguration, 1); @@ -119,54 +116,6 @@ void register_global_keys(HWND handle) } } -// void assign(wchar_t *ptr_first_element, const wchar_t *text) { -// int loc = 0; -// while (text[loc]) { -// ptr_first_element[loc] = text[loc]; -// ++loc; -// } -// ptr_first_element[loc] = 0; -//} - -//HRESULT AddThumbarButtons(HWND hwnd) -//{ -// // Define an array of two buttons. These buttons provide images through an -// // image list and also provide tooltips. -// THUMBBUTTONMASK dwMask = THB_BITMAP | THB_TOOLTIP | THB_FLAGS; -// -// /* -// THUMBBUTTONMASK dwMask; -// UINT iId; -// UINT iBitmap; -// HICON hIcon; -// WCHAR szTip[260]; -// THUMBBUTTONFLAGS dwFlags; -// */ -// -// THUMBBUTTON btn[]{ -// {dwMask, W_KEY_ID_PREV, 0, nullptr, L"Previous song", THBF_ENABLED}, -// {dwMask, W_KEY_ID_PLAY, 0, nullptr, L"Play/pause", THBF_ENABLED}, -// {dwMask, W_KEY_ID_NEXT, 0, nullptr, L"Next song", THBF_ENABLED}}; -// -// ITaskbarList3 * ptbl; -// HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, -// IID_PPV_ARGS(&ptbl)); -// -// if (SUCCEEDED(hr)) -// { -// // Declare the image list that contains the button images. -// // hr = ptbl->ThumbBarSetImageList(hwnd, himl); -// -// if (SUCCEEDED(hr)) -// { -// // Attach the toolbar to the thumbnail. -// hr = ptbl->ThumbBarAddButtons(hwnd, ARRAYSIZE(btn), btn); -// } -// ptbl->Release(); -// } -// return hr; -//} - GdkFilterReturn w32_events_filter_first_everything(GdkXEvent * gdk_xevent, GdkEvent * event, gpointer user_data) @@ -188,8 +137,7 @@ GdkFilterReturn w32_events_filter_first_everything(GdkXEvent * gdk_xevent, (static_cast(event_window)).c_str()); if (event_window.is_main_window(true)) { - event_window. - WindowsWindow::main_window_hidden_ = false; + event_window.WindowsWindow::main_window_hidden_ = false; AUDDBG( "TRANSFER EventReceivingWindow from %s to mainwindow HWND " "%p", @@ -200,32 +148,6 @@ GdkFilterReturn w32_events_filter_first_everything(GdkXEvent * gdk_xevent, grab_keys_onto_window(); } } - // else - // { - // // leaving us. - // AUDDBG("(GettingDown)FALSE %s; %s", - // stringify_win_evt(msg->message).c_str(), - // (static_cast(event_window)).c_str()); - // } - } - // else if (msg->message == WM_CLOSE) - // { - // auto event_window = WindowsWindow::get_window_data(msg->hwnd); - // AUDDBG("%s: ; %s", stringify_win_evt(msg->message).c_str(), - // (static_cast(event_window)).c_str()); - // } - // else if (msg->message == WM_CREATE) - // { - // auto event_window = WindowsWindow::get_window_data(msg->hwnd); - // AUDDBG("%s: ; %s", stringify_win_evt(msg->message).c_str(), - // (static_cast(event_window)).c_str()); - // } - // else if (msg->message == WM_DESTROY) - // { - // auto event_window = WindowsWindow::get_window_data(msg->hwnd); - // AUDDBG("%s: ; %s", stringify_win_evt(msg->message).c_str(), - // (static_cast(event_window)).c_str()); - // } return GDK_FILTER_CONTINUE; } @@ -310,50 +232,7 @@ void release_filter() w32_evts_filter, nullptr); message_receiving_window = nullptr; } -// -// void main_window_created_from_statusbar( -// MainWindowSearchFilterData * const passed_data, -// WindowsWindow & created_main_window) -//{ -// // When window fully shows, must add windows buttons. -// gdk_window_remove_filter( -// reinterpret_cast(passed_data->window_), -// reinterpret_cast(passed_data->function_ptr_), -// passed_data); -// ungrab_keys(); -// release_filter(); -// delete passed_data; -//} -// -// GdkFilterReturn main_window_missing_filter(GdkXEvent * gdk_xevent, -// GdkEvent * event, gpointer -// user_data) -//{ -// auto msg = reinterpret_cast(gdk_xevent); -// if (msg->message == WM_SHOWWINDOW && msg->wParam) -// { -// auto win_data = WindowsWindow::get_window_data(msg->hwnd); -// if (win_data.is_main_window()) -// { -// main_window_created_from_statusbar( -// reinterpret_cast(user_data), -// win_data); -// } -// } -// return GDK_FILTER_CONTINUE; -//} -/** - * GSourceFunc: - * @user_data: data passed to the function, set when the source was - * created with one of the above functions - * - * Specifies the type of function passed to g_timeout_add(), - * g_timeout_add_full(), g_idle_add(), and g_idle_add_full(). - * - * Returns: %FALSE if the source should be removed. #G_SOURCE_CONTINUE and - * #G_SOURCE_REMOVE are more memorable names for the return value. - */ gboolean window_created_callback(gpointer user_data) { AUDDBG("Window created. Do real stuff."); @@ -363,10 +242,7 @@ gboolean window_created_callback(gpointer user_data) return G_SOURCE_REMOVE; } -void win_init() -{ - g_idle_add(&window_created_callback, nullptr); -} +void win_init() { g_idle_add(&window_created_callback, nullptr); } void Hotkey::key_to_string(int key, char ** out_keytext) { @@ -375,7 +251,7 @@ void Hotkey::key_to_string(int key, char ** out_keytext) switch (key) { case VK_OEM_NEC_EQUAL: - // case VK_OEM_FJ_JISHO: (note: same as EQUAL) + // case VK_OEM_FJ_JISHO: (note: same as EQUAL) case VK_OEM_FJ_MASSHOU: case VK_OEM_FJ_TOUROKU: case VK_OEM_FJ_LOYA: diff --git a/src/hotkeyw32/windows_key_str_map.h b/src/hotkeyw32/windows_key_str_map.h index 63cfd124a7..61c495d8d5 100644 --- a/src/hotkeyw32/windows_key_str_map.h +++ b/src/hotkeyw32/windows_key_str_map.h @@ -23,7 +23,7 @@ * * The Audacious team does not consider modular code linking to * Audacious or using our public API to be a derived work. -*/ + */ #ifndef AUDACIOUS_PLUGINS_WINDOWS_KEY_STRINGS_HPP #define AUDACIOUS_PLUGINS_WINDOWS_KEY_STRINGS_HPP diff --git a/src/hotkeyw32/windows_window.cc b/src/hotkeyw32/windows_window.cc index f584e3b433..a317e00bfd 100644 --- a/src/hotkeyw32/windows_window.cc +++ b/src/hotkeyw32/windows_window.cc @@ -23,7 +23,7 @@ * * The Audacious team does not consider modular code linking to * Audacious or using our public API to be a derived work. -*/ + */ #include "windows_window.h" diff --git a/src/hotkeyw32/windows_window.h b/src/hotkeyw32/windows_window.h index bc32c378f7..abb14af1c4 100644 --- a/src/hotkeyw32/windows_window.h +++ b/src/hotkeyw32/windows_window.h @@ -23,7 +23,7 @@ * * The Audacious team does not consider modular code linking to * Audacious or using our public API to be a derived work. -*/ + */ #ifndef _AUD_PLUGINS_HOTKEYW32_WINDOWS_WINDOW_H_INCLUDED_ #define _AUD_PLUGINS_HOTKEYW32_WINDOWS_WINDOW_H_INCLUDED_ @@ -51,7 +51,8 @@ struct WindowsWindow WindowsWindow & operator=(WindowsWindow && right) = default; WindowsWindow(WindowsWindow && right) = default; - WindowsWindow(HWND handle, std::string className, std::string winHeader, AudaciousWindowKind kind); + WindowsWindow(HWND handle, std::string className, std::string winHeader, + AudaciousWindowKind kind); static std::string translated_title(); bool is_main_window(bool allow_hidden = false) const; explicit operator std::string() const;