/* * xmim - X MeeGo Input Method bridge * Copyright (c) 2012 Javier S. Pedro * * Portions from the Smart Common Input Method * Copyright (c) 2002-2005 James Su * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser 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 #include #include #include #include #include "meego/meego-im-connector.h" #include "ximserver.h" #include "xmim.h" Display *x_dpy; Window x_win; XIM x_im; XIC x_ic; char * opt_display = NULL; gint64 opt_xephyr = 0; gboolean opt_verbose = FALSE; gboolean opt_translucent = FALSE; static GMainLoop *main_loop; static MeegoImConnector *m_connector; static GIOChannel *x_chan; static int x_watch; static GOptionEntry entries[] = { { "display", 'd', 0, G_OPTION_ARG_STRING, &opt_display, "X11 display to use", "DISPLAY" }, { "xephyr", 'x', 0, G_OPTION_ARG_INT64, &opt_xephyr, "Xephyr mode", "XEPHYR_WINDOW_ID" }, { "verbose", 'v', 0, G_OPTION_ARG_NONE, &opt_verbose, "Verbose mode", NULL }, { "translucent", 't', 0, G_OPTION_ARG_NONE, &opt_translucent, "Translucent keyboard", NULL }, { NULL } }; static void log_func(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { gboolean def_log_domain = !log_domain || strcmp(log_domain, G_LOG_DOMAIN) == 0; if (log_level & G_LOG_LEVEL_DEBUG) { // A debug message if (opt_verbose) { if (def_log_domain) { g_print("%s\n", message); } else { g_print("%s: %s\n", log_domain, message); } } } else if (log_level & (G_LOG_FLAG_FATAL | G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL)) { if (def_log_domain) { g_printerr("FATAL: %s\n", message); } else { g_printerr("%s FATAL: %s\n", log_domain, message); } abort(); } else if (log_level & (G_LOG_LEVEL_WARNING)) { if (def_log_domain) { g_printerr("WARNING: %s\n", message); } else { g_printerr("%s WARNING: %s\n", log_domain, message); } } else { if (def_log_domain) { g_print("%s\n", message); } else { g_print("%s: %s\n", log_domain, message); } } } static void signal_func(int signum) { g_main_loop_quit(main_loop); } static gboolean x_watch_cb(GIOChannel *source, GIOCondition condition, gpointer data) { XEvent e; while (XPending(x_dpy)) { XNextEvent(x_dpy, &e); if (XFilterEvent(&e, None)) { continue; } } return TRUE; } static Window create_im_window() { int scr = DefaultScreen(x_dpy); Window win = XCreateSimpleWindow(x_dpy, DefaultRootWindow(x_dpy), -1, -1, 1, 1, 0, 0, BlackPixel(x_dpy, scr)); XSetWindowAttributes attrs; unsigned long attrmask; attrs.override_redirect = True; attrmask = CWOverrideRedirect; XChangeWindowAttributes(x_dpy, win, attrmask, &attrs); XSelectInput(x_dpy, win, KeyPressMask | KeyReleaseMask | StructureNotifyMask); XMapWindow(x_dpy, win); return win; } int main(int argc, char *argv[]) { GError *error = NULL; GOptionContext *context; g_log_set_default_handler(log_func, NULL); setlocale(LC_ALL, ""); g_type_init(); context = g_option_context_new("- X11 <-> Meego Input Method bridge daemon"); g_option_context_add_main_entries(context, entries, NULL); if (!g_option_context_parse(context, &argc, &argv, &error)) { g_printerr("option parsing failed: %s\n", error->message); return EXIT_FAILURE; } main_loop = g_main_loop_new(NULL, TRUE); XSetLocaleModifiers(""); // We will open the default IM as a "slave" x_dpy = XOpenDisplay(opt_display); if (!x_dpy) { g_critical("Cannot open X display"); return EXIT_FAILURE; } x_chan = g_io_channel_unix_new(ConnectionNumber(x_dpy)); x_watch = g_io_add_watch(x_chan, G_IO_IN | G_IO_ERR, x_watch_cb, NULL); g_warn_if_fail(XSupportsLocale()); // Open the slave input method x_im = XOpenIM(x_dpy, NULL, NULL, NULL); g_warn_if_fail(x_im); // Create the IM server window x_win = create_im_window(); g_warn_if_fail(x_win != None); // Create the slave input context x_ic = XCreateIC(x_im, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, NULL); g_warn_if_fail(x_ic); m_connector = meego_im_connector_get_singleton(); g_warn_if_fail(m_connector); xims_open(); XFlush(x_dpy); // Flush X11 queue before blocking in the event loop signal(SIGINT, signal_func); signal(SIGTERM, signal_func); g_debug("Server running"); g_main_loop_run(main_loop); g_debug("Server ending"); xims_close(); g_source_remove(x_watch); g_io_channel_unref(x_chan); XDestroyIC(x_ic); XCloseIM(x_im); XCloseDisplay(x_dpy); return EXIT_SUCCESS; }