как добавить передачу событий Xorg в g_main_loop - PullRequest
5 голосов
/ 14 января 2012

У меня облегченное приложение , которое перехватывает события Xorg и dbus.Чтобы сделать это, я инициализировал цикл dbus и запустил g_main_loop, но я не знаю, как добавить обработку событий Xorg естественным образом:

GMainLoop * mainloop = NULL;
mainloop = g_main_loop_new(NULL,FALSE);
dbus_g_thread_init ();
dbus_init();
// <<<<<<<<<<<<<<<<<<<<<<<<<
//1 way using timeout 
//g_timeout_add(100, kbdd_default_iter, mainloop);
//2nd way using pthread
//GThread * t = g_thread_create(kbdd_default_loop, NULL, FALSE, NULL);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>
g_main_loop_run(mainloop);

по умолчанию iter Я проверяю, есть ли ожиданиеX-событие и его обработка.

Оба способа кажутся плохими, во-первых, потому что у меня нет ненужных вызовов для проверки события, во-вторых, потому что я создаю дополнительный поток и вынужден делать дополнительные блокировки.

PS Iзнаю, что я могу использовать gtk lib, но я не хочу иметь зависимости ни от какого инструментария.

1 Ответ

4 голосов
/ 27 января 2012

Если вы хотите добавить обработку событий Xorg в основной цикл без использования тайм-аута (что, как вы заявляете, расточительно), вам нужно добавить источник, который опрашивает X-соединение.Для этого вам нужно подняться ниже уровня абстракции Xlib, чтобы получить базовый дескриптор файла X-соединения.Вот что делает полная программа ниже.Это адаптация C.Отличное учебное пособие по бронированию X11 от Tronche по использованию основного цикла glib для опроса.Я также обратил внимание на «Основы GTK + Development» Эндрю Краузе.

Если это не кажется очень «естественным», это потому, что я сомневаюсь, что есть очень «естественный» способ сделать этодействительно повторная реализация основной части GDK здесь.

/* needed to break into 'Display' struct internals. */
#define XLIB_ILLEGAL_ACCESS

#include <X11/Xlib.h> // Every Xlib program must include this
#include <assert.h>   // I include this to test return values the lazy way
#include <glib.h>

typedef struct _x11_source {
  GSource source;
  Display *dpy;
  Window w;
} x11_source_t;

static gboolean
x11_fd_prepare(GSource *source,
           gint *timeout)
{
  *timeout = -1;
  return FALSE;
}

static gboolean
x11_fd_check (GSource *source)
{
  return TRUE;
}

static gboolean
x11_fd_dispatch(GSource* source, GSourceFunc callback, gpointer user_data)
{
  static gint counter = 0;

  Display *dpy = ((x11_source_t*)source)->dpy;
  Window window = ((x11_source_t*)source)->w;

  XEvent e;

  while (XCheckWindowEvent(dpy,
               window,
               EnterWindowMask,
               &e))
    {
      if (e.type == EnterNotify)
    g_print("We're in!!! (%d)\n", ++counter);
    }

  return TRUE;
}

static gboolean
msg_beacon(gpointer data)
{
  static gint counter = 0;
  g_print("Beacon %d\n", ++counter);
  return TRUE;
}

int
main()
{
      Display *dpy = XOpenDisplay(NULL);
      assert(dpy);

      int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
      int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));

      Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 
                     200, 100, 0, blackColor, blackColor);

      XSelectInput(dpy, w, StructureNotifyMask | EnterWindowMask);
      XMapWindow(dpy, w);

      for (;;) {
    XEvent e;
    XNextEvent(dpy, &e);
    if (e.type == MapNotify)
      break; 
      }

      GMainLoop *mainloop = NULL;
      mainloop = g_main_loop_new(NULL, FALSE);

      /* beacon to demonstrate we're not blocked. */
      g_timeout_add(300, msg_beacon, mainloop);

      GPollFD dpy_pollfd = {dpy->fd,
                G_IO_IN | G_IO_HUP | G_IO_ERR,
                0};

      GSourceFuncs x11_source_funcs = {
    x11_fd_prepare,
    x11_fd_check,
    x11_fd_dispatch,
    NULL, /* finalize */
    NULL, /* closure_callback */
    NULL /* closure_marshal */
      };

      GSource *x11_source =
    g_source_new(&x11_source_funcs, sizeof(x11_source_t));
      ((x11_source_t*)x11_source)->dpy = dpy;
      ((x11_source_t*)x11_source)->w = w;
      g_source_add_poll(x11_source, &dpy_pollfd);
      g_source_attach(x11_source, NULL);

      g_main_loop_run(mainloop);

      return 0;

}
...