client-main.c 8.33 KB
Newer Older
Daiki Ueno's avatar
Daiki Ueno committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/* 
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 * Copyright (C) 2010-2011 Red Hat, Inc.
 * 
 * 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 3 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, see <http://www.gnu.org/licenses/>.
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif  /* HAVE_CONFIG_H */

22
#include <stdlib.h>
23
24
#include <cspi/spi.h>
#include <gtk/gtk.h>
Daiki Ueno's avatar
Daiki Ueno committed
25
#include <glib/gi18n.h>
26
#include <gconf/gconf-client.h>
27
#include "eekboard/eekboard.h"
28
#include "client.h"
Daiki Ueno's avatar
Daiki Ueno committed
29

30
31
32
33
static gboolean opt_system = FALSE;
static gboolean opt_session = FALSE;
static gchar *opt_address = NULL;

34
35
36
37
38
#ifdef HAVE_CSPI
static gboolean opt_focus = FALSE;
static gboolean opt_keystroke = FALSE;
#endif  /* HAVE_CSPI */

Daiki Ueno's avatar
Daiki Ueno committed
39
40
static gchar *opt_keyboard = NULL;

41
42
43
44
45
static gchar *opt_model = NULL;
static gchar *opt_layouts = NULL;
static gchar *opt_options = NULL;

static gboolean opt_fullscreen = FALSE;
Daiki Ueno's avatar
Daiki Ueno committed
46
47

static const GOptionEntry options[] = {
48
49
50
51
52
53
    {"system", 'y', 0, G_OPTION_ARG_NONE, &opt_system,
     N_("Connect to the system bus")},
    {"session", 'e', 0, G_OPTION_ARG_NONE, &opt_session,
     N_("Connect to the session bus")},
    {"address", 'a', 0, G_OPTION_ARG_STRING, &opt_address,
     N_("Connect to the given D-Bus address")},
54
55
56
57
58
59
#ifdef HAVE_CSPI
    {"listen-focus", 'f', 0, G_OPTION_ARG_NONE, &opt_focus,
     N_("Listen focus change events with AT-SPI")},
    {"listen-keystroke", 's', 0, G_OPTION_ARG_NONE, &opt_keystroke,
     N_("Listen keystroke events with AT-SPI")},
#endif  /* HAVE_CSPI */
Daiki Ueno's avatar
Daiki Ueno committed
60
    {"keyboard", 'k', 0, G_OPTION_ARG_STRING, &opt_keyboard,
61
     N_("Specify keyboard")},
62
63
64
65
66
67
68
69
    {"model", '\0', 0, G_OPTION_ARG_STRING, &opt_model,
     N_("Specify model")},
    {"layouts", '\0', 0, G_OPTION_ARG_STRING, &opt_layouts,
     N_("Specify layouts")},
    {"options", '\0', 0, G_OPTION_ARG_STRING, &opt_options,
     N_("Specify options")},
    {"fullscreen", 'F', 0, G_OPTION_ARG_NONE, &opt_fullscreen,
     N_("Create window in fullscreen mode")},
Daiki Ueno's avatar
Daiki Ueno committed
70
71
72
73
    {NULL}
};

static void
74
75
76
on_notify_keyboard_visible (GObject    *object,
                            GParamSpec *spec,
                            gpointer    user_data)
Daiki Ueno's avatar
Daiki Ueno committed
77
{
78
79
80
81
82
83
84
85
    GMainLoop *loop = user_data;
    gboolean visible;

    g_object_get (object, "keyboard-visible", &visible, NULL);

    /* user explicitly closed the window */
    if (!visible && eekboard_context_is_enabled (EEKBOARD_CONTEXT(object)))
        g_main_loop_quit (loop);
Daiki Ueno's avatar
Daiki Ueno committed
86
87
88
}

static void
89
90
on_context_destroyed (EekboardContext *context,
                      gpointer         user_data)
Daiki Ueno's avatar
Daiki Ueno committed
91
{
92
93
94
95
96
97
98
99
100
101
102
103
    GMainLoop *loop = user_data;

    g_main_loop_quit (loop);
}

static void
on_destroyed (EekboardEekboard *eekboard,
              gpointer          user_data)
{
    GMainLoop *loop = user_data;

    g_main_loop_quit (loop);
Daiki Ueno's avatar
Daiki Ueno committed
104
105
106
107
108
}

int
main (int argc, char **argv)
{
109
110
111
    EekboardClient *client;
    EekboardEekboard *eekboard;
    EekboardContext *context;
112
    GBusType bus_type;
113
    GDBusConnection *connection;
Daiki Ueno's avatar
Daiki Ueno committed
114
    GError *error;
115
    GConfClient *gconfc;
116
    GOptionContext *option_context;
117
    GMainLoop *loop;
Daiki Ueno's avatar
Daiki Ueno committed
118

119
120
121
122
    if (!gtk_init_check (&argc, &argv)) {
        g_printerr ("Can't init GTK\n");
        exit (1);
    }
Daiki Ueno's avatar
Daiki Ueno committed
123

124
    option_context = g_option_context_new ("eekboard-desktop-client");
125
126
127
    g_option_context_add_main_entries (option_context, options, NULL);
    g_option_context_parse (option_context, &argc, &argv, NULL);
    g_option_context_free (option_context);
Daiki Ueno's avatar
Daiki Ueno committed
128

129
130
131
132
133
134
135
136
137
138
139
140
141
    if (opt_system)
        bus_type = G_BUS_TYPE_SYSTEM;
    else if (opt_address)
        bus_type = G_BUS_TYPE_NONE;
    else
        bus_type = G_BUS_TYPE_SESSION;

    switch (bus_type) {
    case G_BUS_TYPE_SYSTEM:
    case G_BUS_TYPE_SESSION:
        error = NULL;
        connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
        if (connection == NULL) {
Daiki Ueno's avatar
Daiki Ueno committed
142
            g_printerr ("Can't connect to the bus: %s\n", error->message);
143
144
145
146
147
148
149
150
151
152
153
            exit (1);
        }
        break;
    case G_BUS_TYPE_NONE:
        error = NULL;
        connection = g_dbus_connection_new_for_address_sync (opt_address,
                                                             0,
                                                             NULL,
                                                             NULL,
                                                             &error);
        if (connection == NULL) {
Daiki Ueno's avatar
Daiki Ueno committed
154
            g_printerr ("Can't connect to the bus at %s: %s\n",
155
156
157
158
159
160
161
162
                        opt_address,
                        error->message);
            exit (1);
        }
        break;
    default:
        g_assert_not_reached ();
        break;
Daiki Ueno's avatar
Daiki Ueno committed
163
164
    }

165
166
167
168
    client = eekboard_client_new (connection);
    if (client == NULL) {
        g_printerr ("Can't create a client\n");
        exit (1);
169
170
    }

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
    gconfc = gconf_client_get_default ();

#ifdef HAVE_CSPI
    error = NULL;
    if (opt_focus || opt_keystroke) {
        if (gconf_client_get_bool (gconfc,
                                   "/desktop/gnome/interface/accessibility",
                                   &error) ||
            gconf_client_get_bool (gconfc,
                                   "/desktop/gnome/interface/accessibility2",
                                   &error)) {
            if (SPI_init () != 0) {
                g_printerr ("Can't init CSPI\n");
                exit (1);
            }

            if (opt_focus &&
                !eekboard_client_enable_cspi_focus (client)) {
                g_printerr ("Can't register focus change event listeners\n");
                exit (1);
            }

            if (opt_keystroke &&
                !eekboard_client_enable_cspi_keystroke (client)) {
                g_printerr ("Can't register keystroke event listeners\n");
                exit (1);
            }
        } else {
            g_printerr ("Desktop accessibility support is disabled\n");
            exit (1);
Daiki Ueno's avatar
Daiki Ueno committed
201
        }
202
    }
203
204
#endif  /* HAVE_CSPI */

Daiki Ueno's avatar
Daiki Ueno committed
205
206
207
208
209
210
    if (opt_keyboard && (opt_model || opt_layouts || opt_options)) {
        g_printerr ("Can't use --keyboard option with xklavier options\n");
        exit (1);
    }

    if (opt_keyboard) {
211
212
213
214
215
216
217
218
219
        gchar *file;

        if (g_str_has_suffix (opt_keyboard, ".xml"))
            file = g_strdup (opt_keyboard);
        else
            file = g_strdup_printf ("%s/%s.xml", KEYBOARDDIR, opt_keyboard);
        if (!eekboard_client_load_keyboard_from_file (client, file)) {
            g_printerr ("Can't load keyboard file %s\n", file);
            g_free (file);
Daiki Ueno's avatar
Daiki Ueno committed
220
221
            exit (1);
        }
222
        g_free (file);
Daiki Ueno's avatar
Daiki Ueno committed
223
    } else if (opt_model || opt_layouts || opt_options) {
224
        if (!eekboard_client_set_xkl_config (client,
Daiki Ueno's avatar
Daiki Ueno committed
225
226
227
                                             opt_model,
                                             opt_layouts,
                                             opt_options)) {
228
229
230
231
232
233
            g_printerr ("Can't set xklavier config\n");
            exit (1);
        }
    } else if (!eekboard_client_enable_xkl (client)) {
        g_printerr ("Can't register xklavier event listeners\n");
        exit (1);
Daiki Ueno's avatar
Daiki Ueno committed
234
235
    }

236
237
238
239
#ifdef HAVE_FAKEKEY
    if (!eekboard_client_enable_fakekey (client)) {
        g_printerr ("Can't init fakekey\n");
        exit (1);
Daiki Ueno's avatar
Daiki Ueno committed
240
    }
241
242
243
244
245
246
247
248
249
250
#endif  /* HAVE_FAKEKEY */

    loop = g_main_loop_new (NULL, FALSE);
    if (!opt_focus) {
        g_object_get (client, "context", &context, NULL);
        g_signal_connect (context, "notify::keyboard-visible",
                          G_CALLBACK(on_notify_keyboard_visible), loop);
        g_signal_connect (context, "destroyed",
                          G_CALLBACK(on_context_destroyed), loop);
        g_object_unref (context);
Daiki Ueno's avatar
Daiki Ueno committed
251
252
    }

253
254
255
256
    if (opt_fullscreen) {
        g_object_get (client, "context", &context, NULL);
        eekboard_context_set_fullscreen (context, TRUE, NULL);
        g_object_unref (context);
Daiki Ueno's avatar
Daiki Ueno committed
257
258
    }

259
260
261
    g_object_get (client, "eekboard", &eekboard, NULL);
    g_signal_connect (eekboard, "destroyed",
                      G_CALLBACK(on_destroyed), loop);
Daiki Ueno's avatar
Daiki Ueno committed
262

263
264
    g_main_loop_run (loop);
    g_main_loop_unref (loop);
Daiki Ueno's avatar
Daiki Ueno committed
265

266
    return 0;
Daiki Ueno's avatar
Daiki Ueno committed
267
}