播放器绑键源码分析.
Tofloor
poster avatar
ldmpscript
deepin
2012-12-24 23:17
Author
/*
* Copyright (C) 2004 Lee Willis
*    Borrowed heavily from code by Jan Arne Petersen
*
* 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; either version 2 of the
* License, or (at your option) any later version.
*
* 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, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/

#include

#include "mmkeys.h"

static void mmkeys_class_init (MmKeysClass *klass);
static void mmkeys_init       (MmKeys      *object);
static void mmkeys_finalize   (GObject     *object);

static void grab_mmkey (int key_code, GdkWindow *root);

static GdkFilterReturn filter_mmkeys (GdkXEvent *xevent,
                                      GdkEvent *event,
                                      gpointer data);

enum {
        MM_PLAYPAUSE,
        MM_NEXT,
        MM_PREV,
        MM_STOP,
        LAST_SIGNAL
};

static GObjectClass *parent_class;
static guint signals[LAST_SIGNAL];

static GType type = 0;

GType
mmkeys_get_type (void)
{
        if (!type) {
                static const GTypeInfo info = {
                                sizeof (MmKeysClass),
                                NULL,           /* base_init */
                                NULL,           /* base_finalize */
                                (GClassInitFunc) mmkeys_class_init,
                                NULL,           /* class_finalize */
                                NULL,           /* class_data */
                                sizeof (MmKeys),
                                0,
                                (GInstanceInitFunc) mmkeys_init,
                        };
        /* g_type_register_static */
                type = g_type_register_static (G_TYPE_OBJECT, "MmKeys",
                                       &info, 0);
        }

        return type;
}

static void
mmkeys_class_init (MmKeysClass *klass)
{
        GObjectClass *object_class;
    GObjectClass *object_class;
   
        parent_class = g_type_class_peek_parent (klass);
    g_type_class_peek_parent(klass)
        object_class = (GObjectClass*) klass;

        object_class->finalize = mmkeys_finalize;
    /*注册新的事件*/
        signals[MM_PLAYPAUSE] =
                g_signal_new ("mm_playpause",
                              G_TYPE_FROM_CLASS (klass),
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
                              g_cclosure_marshal_VOID__INT,
                              G_TYPE_NONE, 1, G_TYPE_INT);
        signals[MM_PREV] =
                g_signal_new ("mm_prev",
                              G_TYPE_FROM_CLASS (klass),
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
                              g_cclosure_marshal_VOID__INT,
                              G_TYPE_NONE, 1, G_TYPE_INT);
        signals[MM_NEXT] =
                g_signal_new ("mm_next",
                              G_TYPE_FROM_CLASS (klass),
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
                              g_cclosure_marshal_VOID__INT,
                              G_TYPE_NONE, 1, G_TYPE_INT);
        signals[MM_STOP] =
                g_signal_new ("mm_stop",
                              G_TYPE_FROM_CLASS (klass),
                              G_SIGNAL_RUN_LAST,
                              0,
                              NULL, NULL,
                              g_cclosure_marshal_VOID__INT,
                              G_TYPE_NONE, 1, G_TYPE_INT);
}

static void
mmkeys_finalize (GObject *object)
{
        parent_class->finalize (G_OBJECT(object));
}

#define N_KEYCODES 5

static void
mmkeys_init (MmKeys *object)
{
        int keycodes[N_KEYCODES];
        GdkDisplay *display;
        GdkScreen *screen;
        GdkWindow *root;
        guint i, j;

        display = gdk_display_get_default ();
    /*XStringToKeysym XKeysymToKeycode*/
        keycodes[0] = XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioPrev); // 通过这个函数 转换出 键值.
        keycodes[1] = XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioNext);
        keycodes[2] = XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioPlay);
        keycodes[3] = XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioPause);
        keycodes[4] = XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioStop);

        for (i = 0; i < gdk_display_get_n_screens (display); i++) { /*获取 所有的 display 并进行监控*/
                screen = gdk_display_get_screen (display, i); /*返回screen*/
        
                if (screen != NULL) { /**/
                        root = gdk_screen_get_root_window (screen);/*获取这个root window的screen*/

                        for (j = 0; j < N_KEYCODES; j++) {
                                if (keycodes[j] > 0)
                                        grab_mmkey (keycodes[j], root); /*注册键值,说白了就绑定了*/
                        }
            /*通过这个函数可以捕获ROOT窗口的键.*/
                        gdk_window_add_filter (root,
                                   filter_mmkeys,
                                   object);
                }
        }
}

MmKeys *
mmkeys_new (void)
{
        return MMKEYS (g_object_new (TYPE_MMKEYS, NULL));
}

static void
grab_mmkey (int key_code, GdkWindow *root)
{
        gdk_error_trap_push ();
        XGrabKey (GDK_DISPLAY (),
              key_code,
              AnyModifier,
              GDK_WINDOW_XID (root), True,
              GrabModeAsync, GrabModeAsync);

        gdk_flush ();
        if (gdk_error_trap_pop ()) {
                fprintf (stderr, "Error grabbing key %d, %p\n", key_code, root);
        }
}

static GdkFilterReturn
filter_mmkeys (GdkXEvent *xevent, GdkEvent *event, gpointer data)
{
        XEvent *xev;
        XKeyEvent *key;

        xev = (XEvent *) xevent;
        if (xev->type != KeyPress) { /*type不为键盘按下*/
                return GDK_FILTER_CONTINUE; // gtk文档翻译: event not handled, continue processing.
        }

        key = (XKeyEvent *) xevent;

        if (XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioPlay) == key->keycode) { /*判断是否为 AudioPlay*/
                g_signal_emit (data, signals[MM_PLAYPAUSE], 0, 0);  /*如果是就发送事件,如果我们链接了这个事件,我们就在这个事件里面写代码.就像单击事件一样*/
                return GDK_FILTER_REMOVE;
        } else if (XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioPause) == key->keycode) {
                g_signal_emit (data, signals[MM_PLAYPAUSE], 0, 0);
                return GDK_FILTER_REMOVE;
        } else if (XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioPrev) == key->keycode) {
                g_signal_emit (data, signals[MM_PREV], 0, 0);
                return GDK_FILTER_REMOVE;
        } else if (XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioNext) == key->keycode) {
                g_signal_emit (data, signals[MM_NEXT], 0, 0);
                return GDK_FILTER_REMOVE;
        } else if (XKeysymToKeycode (GDK_DISPLAY (), XF86XK_AudioStop) == key->keycode) {
                g_signal_emit (data, signals[MM_STOP], 0, 0);
                return GDK_FILTER_REMOVE;
        } else {
                return GDK_FILTER_CONTINUE;
        }
}
通过这个例子,其实很容易明白!

就像我们要监听你们家, 先去你们上,下,左右,都装了几个监视器, :  :  :  : 然后我根据监视器发生的事情来做出反应.
Reply Favorite View the author
All Replies
tuhaihe
deepin
2012-12-25 19:22
#1
建议:以后这么长的代码可用 code 格式化一下,否则太长了。。。
Reply View the author