void run_program(GtkButton* button, gpointer user_data) { FcitxSubConfigWidget* widget = (FcitxSubConfigWidget*) user_data; char*args[] = {widget->subconfig->path}; fcitx_utils_start_process(args); }
boolean MainMenuAction(FcitxUIMenu* menu, int index) { FcitxClassicUI* classicui = (FcitxClassicUI*) menu->priv; FcitxInstance* instance = classicui->owner; int length = utarray_len(&menu->shell); if (index == 0) { char* args[] = { "xdg-open", "http://fcitx-im.org/", 0 }; fcitx_utils_start_process(args); } else if (index == length - 1) { /* Exit */ FcitxInstanceEnd(classicui->owner); } else if (index == length - 2) { /* Restart */ fcitx_utils_launch_restart(); } else if (index == length - 3) { /* Configuration */ fcitx_utils_launch_configure_tool(); } else if (index == length - 4) { /* Configuration */ FcitxIM* im = FcitxInstanceGetCurrentIM(classicui->owner); if (im && im->owner) { fcitx_utils_launch_configure_tool_for_addon(im->uniqueName); } else { fcitx_utils_launch_configure_tool(); } } else { FcitxMenuItem* item = (FcitxMenuItem*) utarray_eltptr(&menu->shell, index); if (item && item->type == MENUTYPE_SIMPLE && item->data) { const char* name = item->data; FcitxUIUpdateStatus(instance, name); } } return true; }
FCITX_EXPORT_API void fcitx_utils_launch_tool(const char* name, const char* arg) { char* command = fcitx_utils_get_fcitx_path_with_filename("bindir", name); char* args[] = { command, (char*)(intptr_t)arg, /* parent process haven't even touched this... */ NULL }; fcitx_utils_start_process(args); free(command); }
void* DBusCreate(FcitxInstance* instance) { FcitxDBus *dbusmodule = (FcitxDBus*) fcitx_utils_malloc0(sizeof(FcitxDBus)); FcitxAddon* dbusaddon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), FCITX_DBUS_NAME); dbusmodule->owner = instance; DBusError err; if (FcitxInstanceIsTryReplace(instance)) { fcitx_utils_launch_tool("fcitx-remote", "-e"); sleep(1); } dbus_threads_init_default(); // first init dbus dbus_error_init(&err); int retry = 0; DBusConnection* conn = NULL; char* servicename = NULL; asprintf(&servicename, "%s-%d", FCITX_DBUS_SERVICE, fcitx_utils_get_display_number()); /* do session dbus initialize */ do { if (!getenv("DISPLAY") && !getenv("DBUS_SESSION_BUS_ADDRESS")) { FcitxLog(WARNING, "Without DISPLAY or DBUS_SESSION_BUS_ADDRESS session bus will not work"); break; } /* try to get session dbus */ while (1) { conn = dbus_bus_get(DBUS_BUS_SESSION, &err); if (dbus_error_is_set(&err)) { FcitxLog(WARNING, "Connection Error (%s)", err.message); dbus_error_free(&err); dbus_error_init(&err); } if (NULL == conn && retry < MAX_RETRY_TIMES) { retry ++; sleep(RETRY_INTERVAL * retry); } else { break; } } if (NULL == conn) { break; } if (!dbus_connection_add_filter(conn, DBusModuleFilter, dbusmodule, NULL)) break; if (!dbus_connection_set_watch_functions(conn, DBusAddWatch, DBusRemoveWatch, NULL, &dbusmodule->watches, NULL)) { FcitxLog(WARNING, "Add Watch Function Error"); dbus_error_free(&err); dbus_error_init(&err); dbus_connection_unref(conn); conn = NULL; break; } /* from here we know dbus connection is successful, now we need to register the service */ dbus_connection_set_exit_on_disconnect(conn, FALSE); dbusmodule->conn = conn; boolean request_retry = false; int replaceCountdown = FcitxInstanceIsTryReplace(instance) ? 3 : 0; FcitxInstanceResetTryReplace(instance); do { request_retry = false; // request a name on the bus int ret = dbus_bus_request_name(conn, servicename, DBUS_NAME_FLAG_DO_NOT_QUEUE, &err); if (dbus_error_is_set(&err)) { FcitxLog(WARNING, "Name Error (%s)", err.message); goto dbus_init_failed; } if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { FcitxLog(WARNING, "DBus Service Already Exists"); if (replaceCountdown > 0) { replaceCountdown --; fcitx_utils_launch_tool("fcitx-remote", "-e"); /* sleep for a while and retry */ sleep(1); request_retry = true; continue; } /* if we know fcitx exists, we should exit. */ dbus_error_free(&err); free(servicename); free(dbusmodule); FcitxInstanceEnd(instance); return NULL; } } while (request_retry); dbus_connection_flush(dbusmodule->conn); } while(0); DBusConnection* privconn = NULL; do { int noPrivateDBus = fcitx_utils_get_boolean_env("FCITX_NO_PRIVATE_DBUS", false); if (noPrivateDBus) break; char* file; FILE* dbusfp = FcitxXDGGetFileWithPrefix("dbus", "daemon.conf", "r", &file); if (dbusfp) { fclose(dbusfp); } else { free(file); file = NULL; } dbusmodule->daemon = DBusLaunch(file); fcitx_utils_free(file); if (dbusmodule->daemon.pid == 0) break; privconn = dbus_connection_open(dbusmodule->daemon.address, &err); if (dbus_error_is_set(&err)) { FcitxLog(ERROR, "Private dbus daemon connection error (%s)", err.message); break; } dbus_bus_register(privconn, &err); if (dbus_error_is_set(&err)) { FcitxLog(ERROR, "Private dbus bus register error (%s)", err.message); break; } int ret = dbus_bus_request_name(privconn, servicename, DBUS_NAME_FLAG_DO_NOT_QUEUE, &err); if (dbus_error_is_set(&err)) { FcitxLog(WARNING, "Private Name Error (%s)", err.message); break; } if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { FcitxLog(ERROR, "Private DBus Service Already Exists, fcitx being hacked?"); break; } if (!dbus_connection_add_filter(privconn, DBusModuleFilter, dbusmodule, NULL)) break; if (!dbus_connection_set_watch_functions(privconn, DBusAddWatch, DBusRemoveWatch, NULL, &dbusmodule->watches, NULL)) { FcitxLog(WARNING, "Add Watch Function Error"); break; } char* addressFile = NULL; char* localMachineId = dbus_get_local_machine_id(); asprintf(&addressFile, "%s-%d", localMachineId, fcitx_utils_get_display_number()); dbus_free(localMachineId); FILE* fp = FcitxXDGGetFileUserWithPrefix("dbus", addressFile, "w", NULL); free(addressFile); if (!fp) break; fprintf(fp, "%s", dbusmodule->daemon.address); fwrite("\0", sizeof(char), 1, fp); pid_t curPid = getpid(); fwrite(&dbusmodule->daemon.pid, sizeof(pid_t), 1, fp); fwrite(&curPid, sizeof(pid_t), 1, fp); fclose(fp); dbusmodule->privconn = privconn; char* command = fcitx_utils_get_fcitx_path_with_filename("bindir", "/fcitx-dbus-watcher"); char* pidstring = NULL; asprintf(&pidstring, "%d", dbusmodule->daemon.pid); char* args[] = { command, dbusmodule->daemon.address, pidstring, NULL }; fcitx_utils_start_process(args); free(command); free(pidstring); } while(0); if (!dbusmodule->privconn) { if (privconn) { dbus_connection_unref(privconn); DBusKill(&dbusmodule->daemon); } } FcitxModuleAddFunction(dbusaddon, DBusGetConnection); FcitxModuleAddFunction(dbusaddon, DBusGetPrivateConnection); dbus_error_free(&err); dbusmodule->serviceName = servicename; return dbusmodule; dbus_init_failed: dbus_error_free(&err); fcitx_utils_free(servicename); if (conn) dbus_connection_unref(conn); DBusKill(&dbusmodule->daemon); fcitx_utils_free(dbusmodule); return NULL; }
void FcitxDBusMenuDoEvent(void* arg) { FcitxNotificationItem* notificationitem = (FcitxNotificationItem*) arg; FcitxInstance* instance = notificationitem->owner; int32_t id = notificationitem->pendingActionId; notificationitem->pendingActionId = -1; int32_t menu = ACTION_MENU(id); int32_t index = ACTION_INDEX(id); if (index <= 0) return; if (menu == 0) { if (index <= 8 && index > 0) { switch(index) { case 1: { char* args[] = { "xdg-open", "http://fcitx-im.org/", 0 }; fcitx_utils_start_process(args); } break; case 4: { FcitxIM* im = FcitxInstanceGetCurrentIM(instance); if (im && im->owner) { fcitx_utils_launch_configure_tool_for_addon(im->uniqueName); } else { fcitx_utils_launch_configure_tool(); } } break; case 5: fcitx_utils_launch_configure_tool(); break; case 6: fcitx_utils_launch_restart(); break; case 7: FcitxInstanceEnd(instance); break; } } else { int index = STATUS_INDEX(id); const char* name = NULL; if (STATUS_ISCOMP(id)) { UT_array* uicompstats = FcitxInstanceGetUIComplexStats(instance); FcitxUIComplexStatus* compstatus = (FcitxUIComplexStatus*) utarray_eltptr(uicompstats, index); if (compstatus) { name = compstatus->name; } } else { UT_array* uistats = FcitxInstanceGetUIStats(instance); FcitxUIStatus* status = (FcitxUIStatus*) utarray_eltptr(uistats, index); if (status) { name = status->name; } } if (name) { FcitxUIUpdateStatus(instance, name); } } } else if (menu > 0) { UT_array* uimenus = FcitxInstanceGetUIMenus(instance); FcitxUIMenu** menup = (FcitxUIMenu**) utarray_eltptr(uimenus, menu - 1), *menu; if (!menup) return; menu = *menup; if (menu->MenuAction) { menu->MenuAction(menu, index - 1); } } }