1
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2
/* vim:set et sts=4: */
3
/* ibus - The Input Bus
4
* Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
5
* Copyright (C) 2008-2010 Red Hat, Inc.
7
* This library is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2 of the License, or (at your option) any later version.
12
* This library is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this library; if not, write to the
19
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
* Boston, MA 02111-1307, USA.
22
#include <dbus/dbus.h>
23
#include "ibusinternal.h"
27
* @source: The parent GSource.
28
* @connection: The connection to dispatch.
30
* A GSource subclass for dispatching DBusConnection messages.
31
* We need this on top of the IO handlers, because sometimes
32
* there are messages to dispatch queued up but no IO pending.
37
DBusConnection *connection;
40
static gboolean message_queue_prepare (GSource *source,
42
static gboolean message_queue_check (GSource *source);
43
static gboolean message_queue_dispatch (GSource *source,
47
static const GSourceFuncs message_queue_funcs = {
48
message_queue_prepare,
50
message_queue_dispatch,
55
message_queue_prepare (GSource *source,
58
DBusConnection *connection = ((IBusMessageQueue *)source)->connection;
62
return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
66
message_queue_check (GSource *source)
72
message_queue_dispatch (GSource *source,
76
DBusConnection *connection = ((IBusMessageQueue *)source)->connection;
78
dbus_connection_ref (connection);
80
/* Only dispatch once - we don't want to starve other GSource */
81
dbus_connection_dispatch (connection);
83
dbus_connection_unref (connection);
90
* @context: The main context.
91
* @ios: All IOHandler.
92
* @timeouts: All TimeoutHandler.
93
* @connection: NULL if this is really for a server not a connection.
94
* @message_queue_source: IBusMessageQueue.
97
GSource *message_queue_source; /**< IBusMessageQueue */
100
GMainContext *context; /**< the main context */
101
GSList *ios; /**< all IOHandler */
102
GSList *timeouts; /**< all TimeoutHandler */
103
DBusConnection *connection; /**< NULL if this is really for a server not a connection */
104
GSource *message_queue_source; /**< IBusMessageQueue */
119
DBusTimeout *timeout;
122
dbus_int32_t _dbus_gmain_connection_slot = -1;
123
static dbus_int32_t server_slot = -1;
125
static ConnectionSetup*
126
connection_setup_new (GMainContext *context,
127
DBusConnection *connection)
131
cs = g_slice_new0 (ConnectionSetup);
133
g_assert (context != NULL);
135
cs->context = context;
136
g_main_context_ref (cs->context);
139
cs->connection = connection;
141
cs->message_queue_source = g_source_new ((GSourceFuncs *) &message_queue_funcs,
142
sizeof (IBusMessageQueue));
143
((IBusMessageQueue*)cs->message_queue_source)->connection = connection;
144
g_source_attach (cs->message_queue_source, cs->context);
150
io_handler_source_finalized (gpointer data)
157
dbus_watch_set_data (handler->watch, NULL, NULL);
159
g_slice_free (IOHandler, handler);
163
io_handler_destroy_source (void *data)
169
if (handler->source) {
170
GSource *source = handler->source;
171
handler->source = NULL;
172
handler->cs->ios = g_slist_remove (handler->cs->ios, handler);
173
g_source_destroy (source);
174
g_source_unref (source);
179
io_handler_watch_freed (void *data)
185
handler->watch = NULL;
187
io_handler_destroy_source (handler);
191
io_handler_dispatch (GIOChannel *source,
192
GIOCondition condition,
196
guint dbus_condition = 0;
197
DBusConnection *connection;
201
connection = handler->cs->connection;
204
dbus_connection_ref (connection);
206
if (condition & G_IO_IN)
207
dbus_condition |= DBUS_WATCH_READABLE;
208
if (condition & G_IO_OUT)
209
dbus_condition |= DBUS_WATCH_WRITABLE;
210
if (condition & G_IO_ERR)
211
dbus_condition |= DBUS_WATCH_ERROR;
212
if (condition & G_IO_HUP)
213
dbus_condition |= DBUS_WATCH_HANGUP;
215
/* Note that we don't touch the handler after this, because
216
* dbus may have disabled the watch and thus killed the
219
dbus_watch_handle (handler->watch, dbus_condition);
223
dbus_connection_unref (connection);
229
connection_setup_add_watch (ConnectionSetup *cs,
233
GIOCondition condition;
237
if (!dbus_watch_get_enabled (watch))
240
g_assert (dbus_watch_get_data (watch) == NULL);
242
flags = dbus_watch_get_flags (watch);
244
condition = G_IO_ERR | G_IO_HUP;
245
if (flags & DBUS_WATCH_READABLE)
246
condition |= G_IO_IN;
247
if (flags & DBUS_WATCH_WRITABLE)
248
condition |= G_IO_OUT;
250
handler = g_slice_new (IOHandler);
252
handler->watch = watch;
254
channel = g_io_channel_unix_new (dbus_watch_get_unix_fd (watch));
256
handler->source = g_io_create_watch (channel, condition);
257
g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler,
258
io_handler_source_finalized);
259
g_source_attach (handler->source, cs->context);
261
cs->ios = g_slist_prepend (cs->ios, handler);
263
dbus_watch_set_data (watch, handler, io_handler_watch_freed);
264
g_io_channel_unref (channel);
268
connection_setup_remove_watch (ConnectionSetup *cs,
273
handler = dbus_watch_get_data (watch);
278
io_handler_destroy_source (handler);
282
timeout_handler_source_finalized (gpointer data)
284
TimeoutHandler *handler;
288
if (handler->timeout)
289
dbus_timeout_set_data (handler->timeout, NULL, NULL);
291
g_slice_free (TimeoutHandler, handler);
295
timeout_handler_destroy_source (void *data)
297
TimeoutHandler *handler;
301
if (handler->source) {
302
GSource *source = handler->source;
303
handler->source = NULL;
304
handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler);
305
g_source_destroy (source);
306
g_source_unref (source);
311
timeout_handler_timeout_freed (void *data)
313
TimeoutHandler *handler;
317
handler->timeout = NULL;
319
timeout_handler_destroy_source (handler);
323
timeout_handler_dispatch (gpointer data)
325
TimeoutHandler *handler;
329
dbus_timeout_handle (handler->timeout);
335
connection_setup_add_timeout (ConnectionSetup *cs,
336
DBusTimeout *timeout)
338
TimeoutHandler *handler;
340
if (!dbus_timeout_get_enabled (timeout))
343
g_assert (dbus_timeout_get_data (timeout) == NULL);
345
handler = g_slice_new0 (TimeoutHandler);
347
handler->timeout = timeout;
349
handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
350
g_source_set_callback (handler->source, timeout_handler_dispatch, handler,
351
timeout_handler_source_finalized);
352
g_source_attach (handler->source, handler->cs->context);
354
cs->timeouts = g_slist_prepend (cs->timeouts, handler);
356
dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed);
360
connection_setup_remove_timeout (ConnectionSetup *cs,
361
DBusTimeout *timeout)
363
TimeoutHandler *handler;
365
handler = dbus_timeout_get_data (timeout);
370
timeout_handler_destroy_source (handler);
374
connection_setup_free (ConnectionSetup *cs)
377
io_handler_destroy_source (cs->ios->data);
380
timeout_handler_destroy_source (cs->timeouts->data);
382
if (cs->message_queue_source) {
385
source = cs->message_queue_source;
386
cs->message_queue_source = NULL;
388
g_source_destroy (source);
389
g_source_unref (source);
392
g_main_context_unref (cs->context);
393
g_slice_free (ConnectionSetup, cs);
397
add_watch (DBusWatch *watch,
404
connection_setup_add_watch (cs, watch);
410
remove_watch (DBusWatch *watch,
417
connection_setup_remove_watch (cs, watch);
421
watch_toggled (DBusWatch *watch,
424
/* Because we just exit on OOM, enable/disable is
425
* no different from add/remove
427
if (dbus_watch_get_enabled (watch))
428
add_watch (watch, data);
430
remove_watch (watch, data);
434
add_timeout (DBusTimeout *timeout,
441
if (!dbus_timeout_get_enabled (timeout))
444
connection_setup_add_timeout (cs, timeout);
450
remove_timeout (DBusTimeout *timeout,
457
connection_setup_remove_timeout (cs, timeout);
461
timeout_toggled (DBusTimeout *timeout,
464
/* Because we just exit on OOM, enable/disable is
465
* no different from add/remove
467
if (dbus_timeout_get_enabled (timeout))
468
add_timeout (timeout, data);
470
remove_timeout (timeout, data);
474
wakeup_main (void *data)
476
ConnectionSetup *cs = data;
478
g_main_context_wakeup (cs->context);
482
/* Move to a new context */
483
static ConnectionSetup*
484
connection_setup_new_from_old (GMainContext *context,
485
ConnectionSetup *old)
490
g_assert (old->context != context);
492
cs = connection_setup_new (context, old->connection);
495
while (tmp != NULL) {
496
IOHandler *handler = tmp->data;
498
connection_setup_add_watch (cs, handler->watch);
504
while (tmp != NULL) {
505
TimeoutHandler *handler = tmp->data;
507
connection_setup_add_timeout (cs, handler->timeout);
515
/** @} */ /* End of GLib bindings internals */
517
/* @addtogroup IBusLib
522
* dbus_connection_setup_with_g_main:
523
* @connection: the connection
524
* @context: the #GMainContext or #NULL for default context
526
* Sets the watch and timeout functions of a #DBusConnection
527
* to integrate the connection with the GLib main loop.
528
* Pass in #NULL for the #GMainContext unless you're
529
* doing something specialized.
531
* If called twice for the same context, does nothing the second
532
* time. If called once with context A and once with context B,
533
* context B replaces context A as the context monitoring the
537
dbus_connection_setup (DBusConnection *connection,
538
GMainContext *context)
540
ConnectionSetup *old_setup;
544
/* FIXME we never free the slot, so its refcount just keeps growing,
545
* which is kind of broken.
547
dbus_connection_allocate_data_slot (&_dbus_gmain_connection_slot);
548
if (_dbus_gmain_connection_slot < 0)
552
context = g_main_context_default ();
556
old_setup = dbus_connection_get_data (connection, _dbus_gmain_connection_slot);
557
if (old_setup != NULL) {
558
if (old_setup->context == context)
559
return; /* nothing to do */
561
cs = connection_setup_new_from_old (context, old_setup);
563
/* Nuke the old setup */
564
dbus_connection_set_data (connection, _dbus_gmain_connection_slot, NULL, NULL);
569
cs = connection_setup_new (context, connection);
571
if (!dbus_connection_set_data (connection, _dbus_gmain_connection_slot, cs,
572
(DBusFreeFunction)connection_setup_free))
575
if (!dbus_connection_set_watch_functions (connection,
582
if (!dbus_connection_set_timeout_functions (connection,
589
dbus_connection_set_wakeup_main_function (connection,
596
g_error ("Not enough memory to set up DBusConnection for use with GLib");
600
* dbus_server_setup_with_g_main:
601
* @server: the server
602
* @context: the #GMainContext or #NULL for default
604
* Sets the watch and timeout functions of a #DBusServer
605
* to integrate the server with the GLib main loop.
606
* In most cases the context argument should be #NULL.
608
* If called twice for the same context, does nothing the second
609
* time. If called once with context A and once with context B,
610
* context B replaces context A as the context monitoring the
614
dbus_server_setup (DBusServer *server,
615
GMainContext *context)
617
ConnectionSetup *old_setup;
621
/* FIXME we never free the slot, so its refcount just keeps growing,
622
* which is kind of broken.
624
dbus_server_allocate_data_slot (&server_slot);
629
context = g_main_context_default ();
633
old_setup = dbus_server_get_data (server, server_slot);
634
if (old_setup != NULL) {
635
if (old_setup->context == context)
636
return; /* nothing to do */
638
cs = connection_setup_new_from_old (context, old_setup);
640
/* Nuke the old setup */
641
dbus_server_set_data (server, server_slot, NULL, NULL);
646
cs = connection_setup_new (context, NULL);
648
if (!dbus_server_set_data (server, server_slot, cs,
649
(DBusFreeFunction)connection_setup_free))
652
if (!dbus_server_set_watch_functions (server,
659
if (!dbus_server_set_timeout_functions (server,
669
g_error ("Not enough memory to set up DBusServer for use with GLib");