boolean IsMouseInOtherMenu(XlibMenu *xlibMenu, int x, int y) { FcitxClassicUI *classicui = xlibMenu->parent.owner; FcitxInstance* instance = classicui->owner; FcitxUIMenu** menupp; UT_array* uimenus = FcitxInstanceGetUIMenus(instance); for (menupp = (FcitxUIMenu **) utarray_front(uimenus); menupp != NULL; menupp = (FcitxUIMenu **) utarray_next(uimenus, menupp) ) { XlibMenu* otherXlibMenu = (XlibMenu*)(*menupp)->uipriv[classicui->isfallback]; if (otherXlibMenu == xlibMenu) continue; XWindowAttributes attr; XGetWindowAttributes(classicui->dpy, otherXlibMenu->parent.wId, &attr); if (attr.map_state != IsUnmapped && FcitxUIIsInBox(x, y, attr.x, attr.y, attr.width, attr.height)) { return true; } } XlibMenu* otherXlibMenu = classicui->mainMenuWindow; if (otherXlibMenu == xlibMenu) return false; XWindowAttributes attr; XGetWindowAttributes(classicui->dpy, otherXlibMenu->parent.wId, &attr); if (attr.map_state != IsUnmapped && FcitxUIIsInBox(x, y, attr.x, attr.y, attr.width, attr.height)) { return true; } return false; }
void* LightUICreate(FcitxInstance* instance) { FcitxModuleFunctionArg arg; FcitxLightUI* lightui = fcitx_utils_malloc0(sizeof(FcitxLightUI)); FcitxAddon* lightuiaddon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), FCITX_LIGHT_UI_NAME); lightui->owner = instance; if (!LoadLightUIConfig(lightui)) { free(lightui); return NULL; } lightui->dpy = InvokeFunction(instance, FCITX_X11, GETDISPLAY, arg); if (lightui->dpy == NULL) { free(lightui); return NULL; } lightui->isfallback = FcitxUIIsFallback(instance, lightuiaddon); lightui->iScreen = DefaultScreen(lightui->dpy); CreateFont(lightui); lightui->protocolAtom = XInternAtom (lightui->dpy, "WM_PROTOCOLS", False); lightui->killAtom = XInternAtom (lightui->dpy, "WM_DELETE_WINDOW", False); /* Main Menu Initial */ FcitxMenuInit(&lightui->mainMenu); FcitxUIMenu **menupp; UT_array* uimenus = FcitxInstanceGetUIMenus(instance); for (menupp = (FcitxUIMenu **) utarray_front(uimenus); menupp != NULL; menupp = (FcitxUIMenu **) utarray_next(uimenus, menupp) ) { FcitxUIMenu * menup = *menupp; if (!menup->isSubMenu) FcitxMenuAddMenuItem(&lightui->mainMenu, menup->name, MENUTYPE_SUBMENU, menup); } FcitxMenuAddMenuItem(&lightui->mainMenu, NULL, MENUTYPE_DIVLINE, NULL); FcitxMenuAddMenuItem(&lightui->mainMenu, _("Configure"), MENUTYPE_SIMPLE, NULL); FcitxMenuAddMenuItem(&lightui->mainMenu, _("Exit"), MENUTYPE_SIMPLE, NULL); lightui->mainMenu.MenuAction = MainMenuAction; lightui->mainMenu.priv = lightui; lightui->mainMenu.mark = -1; lightui->inputWindow = CreateInputWindow(lightui); lightui->mainWindow = CreateMainWindow(lightui); lightui->trayWindow = CreateTrayWindow(lightui); lightui->mainMenuWindow = CreateMainMenuWindow(lightui); FcitxIMEventHook resethk; resethk.arg = lightui; resethk.func = LightUIInputReset; FcitxInstanceRegisterResetInputHook(instance, resethk); return lightui; }
void CloseAllMenuWindow(FcitxClassicUI *classicui) { FcitxInstance* instance = classicui->owner; FcitxUIMenu** menupp; UT_array* uimenus = FcitxInstanceGetUIMenus(instance); for (menupp = (FcitxUIMenu **) utarray_front(uimenus); menupp != NULL; menupp = (FcitxUIMenu **) utarray_next(uimenus, menupp) ) { XlibMenu* xlibMenu = (XlibMenu*)(*menupp)->uipriv[classicui->isfallback]; XlibMenuHide(xlibMenu); } XlibMenuHide(classicui->mainMenuWindow); }
FCITX_EXPORT_API FcitxUIMenu* FcitxUIGetMenuByStatusName(FcitxInstance* instance, const char* name) { FcitxUIStatus* status = FcitxUIGetStatusByName(instance, name); if (!status) { FcitxUIComplexStatus* compstatus = FcitxUIGetComplexStatusByName(instance, name); if (!compstatus) return NULL; } UT_array* uimenus = FcitxInstanceGetUIMenus(instance); FcitxUIMenu** menupp, *menup = NULL; for (menupp = (FcitxUIMenu **) utarray_front(uimenus); menupp != NULL; menupp = (FcitxUIMenu **) utarray_next(uimenus, menupp) ) { if ((*menupp)->candStatusBind && strcmp((*menupp)->candStatusBind, name) == 0) { menup = *menupp; break; } } return menup; }
void* ClassicUICreate(FcitxInstance* instance) { FcitxAddon* classicuiaddon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), FCITX_CLASSIC_UI_NAME); FcitxModuleFunctionArg arg; FcitxClassicUI* classicui = fcitx_utils_malloc0(sizeof(FcitxClassicUI)); classicui->owner = instance; if (!LoadClassicUIConfig(classicui)) { free(classicui); return NULL; } if (GetSkinDesc() == NULL) { free(classicui); return NULL; } classicui->dpy = InvokeFunction(instance, FCITX_X11, GETDISPLAY, arg); if (classicui->dpy == NULL) { free(classicui); return NULL; } if (LoadSkinConfig(&classicui->skin, &classicui->skinType)) { free(classicui); return NULL; } classicui->isfallback = FcitxUIIsFallback(instance, classicuiaddon); classicui->iScreen = DefaultScreen(classicui->dpy); classicui->protocolAtom = XInternAtom(classicui->dpy, "WM_PROTOCOLS", False); classicui->killAtom = XInternAtom(classicui->dpy, "WM_DELETE_WINDOW", False); InitSkinMenu(classicui); FcitxUIRegisterMenu(instance, &classicui->skinMenu); /* Main Menu Initial */ FcitxMenuInit(&classicui->mainMenu); FcitxMenuAddMenuItem(&classicui->mainMenu, _("About Fcitx"), MENUTYPE_SIMPLE, NULL); FcitxMenuAddMenuItem(&classicui->mainMenu, _("Online Help"), MENUTYPE_SIMPLE, NULL); FcitxMenuAddMenuItem(&classicui->mainMenu, NULL, MENUTYPE_DIVLINE, NULL); FcitxUIMenu **menupp; UT_array* uimenus = FcitxInstanceGetUIMenus(instance); for (menupp = (FcitxUIMenu **) utarray_front(uimenus); menupp != NULL; menupp = (FcitxUIMenu **) utarray_next(uimenus, menupp) ) { FcitxUIMenu * menup = *menupp; if (!menup->isSubMenu) FcitxMenuAddMenuItem(&classicui->mainMenu, menup->name, MENUTYPE_SUBMENU, menup); } FcitxMenuAddMenuItem(&classicui->mainMenu, NULL, MENUTYPE_DIVLINE, NULL); FcitxMenuAddMenuItem(&classicui->mainMenu, _("Configure"), MENUTYPE_SIMPLE, NULL); FcitxMenuAddMenuItem(&classicui->mainMenu, _("Exit"), MENUTYPE_SIMPLE, NULL); classicui->mainMenu.MenuAction = MainMenuAction; classicui->mainMenu.priv = classicui; classicui->mainMenu.mark = -1; classicui->inputWindow = CreateInputWindow(classicui); classicui->mainWindow = CreateMainWindow(classicui); classicui->trayWindow = CreateTrayWindow(classicui); classicui->aboutWindow = CreateAboutWindow(classicui); classicui->messageWindow = CreateMessageWindow(classicui); classicui->mainMenuWindow = CreateMainMenuWindow(classicui); FcitxIMEventHook resethk; resethk.arg = classicui; resethk.func = ClassicUIInputReset; FcitxInstanceRegisterResetInputHook(instance, resethk); DisplaySkin(classicui, classicui->skinType); /* ensure order ! */ AddFunction(classicuiaddon, ClassicUILoadImage); AddFunction(classicuiaddon, ClassicUIGetKeyBoardFontColor); AddFunction(classicuiaddon, ClassicUIGetFont); return classicui; }
void FcitxDBusMenuFillLayooutItem(FcitxNotificationItem* notificationitem, int32_t id, int depth, FcitxStringHashSet* properties, DBusMessageIter* iter) { FcitxInstance* instance = notificationitem->owner; DBusMessageIter sub, array; dbus_message_iter_open_container(iter, DBUS_TYPE_STRUCT, NULL, &sub); dbus_message_iter_append_basic(&sub, DBUS_TYPE_INT32, &id); FcitxDBusMenuFillProperty(notificationitem, id, properties, &sub); dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "v", &array); /* for dbus menu, we have * root (0,0) -> online help (0,1) * -> separator (0,2) * -> some status (0,8 + X) do cache * -> separator (0,8) * -> registered menu (x,0) -> (x,1) , (x,2), (x,3) * -> separator (0,3) * -> configure current (0,4) * -> configure (0,5) * -> restart (0,6) * -> exit (0,7) */ /* using != 0 can make -1 recursive to infinite */ if (depth != 0) { int32_t menu = ACTION_MENU(id); int32_t index = ACTION_INDEX(id); UT_array* uimenus = FcitxInstanceGetUIMenus(instance); /* we ONLY support submenu in top level menu */ if (menu == 0) { if (index == 0) { FcitxDBusMenuFillLayooutItemWrap(notificationitem, ACTION_ID(0,1), depth - 1, properties, &array); FcitxDBusMenuFillLayooutItemWrap(notificationitem, ACTION_ID(0,2), depth - 1, properties, &array); boolean flag = false; /* copied from classicui.c */ FcitxUIStatus* status; UT_array* uistats = FcitxInstanceGetUIStats(instance); int i; for (i = 0, status = (FcitxUIStatus*) utarray_front(uistats); status != NULL; i++, status = (FcitxUIStatus*) utarray_next(uistats, status)) { if (!status->visible) continue; flag = true; FcitxDBusMenuFillLayooutItemWrap(notificationitem, STATUS_ID(0,i), depth - 1, properties, &array); } FcitxUIComplexStatus* compstatus; UT_array* uicompstats = FcitxInstanceGetUIComplexStats(instance); for (i = 0, compstatus = (FcitxUIComplexStatus*) utarray_front(uicompstats); compstatus != NULL; i++, compstatus = (FcitxUIComplexStatus*) utarray_next(uicompstats, compstatus) ) { if (!compstatus->visible) continue; if (FcitxUIGetMenuByStatusName(instance, compstatus->name)) continue; flag = true; FcitxDBusMenuFillLayooutItemWrap(notificationitem, STATUS_ID(1,i), depth - 1, properties, &array); } if (flag) FcitxDBusMenuFillLayooutItemWrap(notificationitem, ACTION_ID(0,8), depth - 1, properties, &array); if (utarray_len(uimenus) > 0) { FcitxUIMenu **menupp; int i = 1; for (menupp = (FcitxUIMenu **) utarray_front(uimenus); menupp != NULL; menupp = (FcitxUIMenu **) utarray_next(uimenus, menupp)) { do { if (!menupp) { break; } FcitxUIMenu* menup = *menupp; if (!menup->visible) { break; } if (menup->candStatusBind) { FcitxUIComplexStatus* compStatus = FcitxUIGetComplexStatusByName(instance, menup->candStatusBind); if (compStatus && !compStatus->visible) { break; } } FcitxDBusMenuFillLayooutItemWrap(notificationitem, ACTION_ID(i,0), depth - 1, properties, &array); } while(0); i ++; } FcitxDBusMenuFillLayooutItemWrap(notificationitem, ACTION_ID(0,3), depth - 1, properties, &array); } FcitxDBusMenuFillLayooutItemWrap(notificationitem, ACTION_ID(0,4), depth - 1, properties, &array); FcitxDBusMenuFillLayooutItemWrap(notificationitem, ACTION_ID(0,5), depth - 1, properties, &array); FcitxDBusMenuFillLayooutItemWrap(notificationitem, ACTION_ID(0,6), depth - 1, properties, &array); FcitxDBusMenuFillLayooutItemWrap(notificationitem, ACTION_ID(0,7), depth - 1, properties, &array); } } else { if (index == 0) { FcitxUIMenu** menupp = (FcitxUIMenu**) utarray_eltptr(uimenus, menu - 1), *menup; if (menupp) { menup = *menupp; menup->UpdateMenu(menup); unsigned int i = 0; unsigned int len = utarray_len(&menup->shell); for (i = 0; i < len; i++) { FcitxDBusMenuFillLayooutItemWrap(notificationitem, ACTION_ID(menu,i + 1), depth - 1, properties, &array); } } } } } dbus_message_iter_close_container(&sub, &array); dbus_message_iter_close_container(iter, &sub); }
void FcitxDBusMenuFillProperty(FcitxNotificationItem* notificationitem, int32_t id, FcitxStringHashSet* properties, DBusMessageIter* iter) { FcitxInstance* instance = notificationitem->owner; /* append a{sv} */ DBusMessageIter sub; dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &sub); int32_t menu = ACTION_MENU(id); int32_t index = ACTION_INDEX(id); /* index == 0 means it has a sub menu */ if (index == 0) { const char* value = "submenu"; FcitxDBusMenuAppendProperty(&sub, properties, "children-display", DBUS_TYPE_STRING, &value); } if (menu == 0) { if (index <= 8 && index > 0) { const char* value; switch(index) { case 1: value = _("Online Help"); FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &value); value = "help-contents"; FcitxDBusMenuAppendProperty(&sub, properties, "icon-name", DBUS_TYPE_STRING, &value); break; case 2: case 3: case 8: value = "separator"; FcitxDBusMenuAppendProperty(&sub, properties, "type", DBUS_TYPE_STRING, &value); break; case 4: value = _("Configure Current Input Method"); FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &value); break; case 5: value = _("Configure"); FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &value); /* this icon sucks on KDE, why configure doesn't have "configure" */ #if 0 value = "preferences-system"; FcitxDBusMenuAppendProperty(&sub, properties, "icon-name", DBUS_TYPE_STRING, &value); #endif break; case 6: value = _("Restart"); FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &value); value = "view-refresh"; FcitxDBusMenuAppendProperty(&sub, properties, "icon-name", DBUS_TYPE_STRING, &value); break; case 7: value = _("Exit"); FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &value); value = "application-exit"; FcitxDBusMenuAppendProperty(&sub, properties, "icon-name", DBUS_TYPE_STRING, &value); break; } } else { int index = STATUS_INDEX(id); const char* name = NULL; const char* icon = NULL; char* needfree = NULL; if (STATUS_ISCOMP(id)) { UT_array* uicompstats = FcitxInstanceGetUIComplexStats(instance); FcitxUIComplexStatus* compstatus = (FcitxUIComplexStatus*) utarray_eltptr(uicompstats, index); if (compstatus) { name = compstatus->shortDescription; icon = compstatus->getIconName(compstatus->arg); if (CheckAddPrefix(&icon)) { fcitx_utils_alloc_cat_str(needfree, "fcitx-", icon); icon = needfree; } } } else { UT_array* uistats = FcitxInstanceGetUIStats(instance); FcitxUIStatus* status = (FcitxUIStatus*) utarray_eltptr(uistats, index); if (status) { name = status->shortDescription; fcitx_utils_alloc_cat_str(needfree, "fcitx-", status->name, ((status->getCurrentStatus(status->arg)) ? "-active" : "-inactive")); icon = needfree; } } if (name) { FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &name); } if (icon) { FcitxDBusMenuAppendProperty(&sub, properties, "icon-name", DBUS_TYPE_STRING, &icon); } fcitx_utils_free(needfree); } } else { UT_array* uimenus = FcitxInstanceGetUIMenus(instance); FcitxUIMenu** menupp = (FcitxUIMenu**) utarray_eltptr(uimenus, menu - 1), *menup; if (menupp) { menup = *menupp; if (index == 0) { FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &menup->name); } else if (index > 0) { FcitxMenuItem* item = (FcitxMenuItem*) utarray_eltptr(&menup->shell, index - 1); if (item) { FcitxDBusMenuAppendProperty(&sub, properties, "label", DBUS_TYPE_STRING, &item->tipstr); if (menup->mark != -1) { const char* radio = "radio"; FcitxDBusMenuAppendProperty(&sub, properties, "toggle-type", DBUS_TYPE_STRING, &radio); int32_t toggleState = 0; if (menup->mark == index - 1) { toggleState = 1; } FcitxDBusMenuAppendProperty(&sub, properties, "toggle-state", DBUS_TYPE_INT32, &toggleState); } } } } } dbus_message_iter_close_container(iter, &sub); }
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); } } }
static void UpdateMainMenu(FcitxUIMenu* menu) { FcitxClassicUI* classicui = (FcitxClassicUI*) menu->priv; FcitxInstance* instance = classicui->owner; FcitxMenuClear(menu); FcitxMenuAddMenuItem(menu, _("Online Help"), MENUTYPE_SIMPLE, NULL); FcitxMenuAddMenuItem(menu, NULL, MENUTYPE_DIVLINE, NULL); boolean flag = false; FcitxUIStatus* status; UT_array* uistats = FcitxInstanceGetUIStats(instance); for (status = (FcitxUIStatus*) utarray_front(uistats); status != NULL; status = (FcitxUIStatus*) utarray_next(uistats, status) ) { FcitxClassicUIStatus* privstat = GetPrivateStatus(status); if (privstat == NULL || !status->visible || privstat->avail ) continue; flag = true; FcitxMenuAddMenuItemWithData(menu, status->shortDescription, MENUTYPE_SIMPLE, NULL, strdup(status->name)); } FcitxUIComplexStatus* compstatus; UT_array* uicompstats = FcitxInstanceGetUIComplexStats(instance); for (compstatus = (FcitxUIComplexStatus*) utarray_front(uicompstats); compstatus != NULL; compstatus = (FcitxUIComplexStatus*) utarray_next(uicompstats, compstatus) ) { FcitxClassicUIStatus* privstat = GetPrivateStatus(compstatus); if (privstat == NULL || !compstatus->visible || privstat->avail) continue; if (FcitxUIGetMenuByStatusName(instance, compstatus->name)) continue; flag = true; FcitxMenuAddMenuItemWithData(menu, compstatus->shortDescription, MENUTYPE_SIMPLE, NULL, strdup(compstatus->name)); } if (flag) FcitxMenuAddMenuItem(menu, NULL, MENUTYPE_DIVLINE, NULL); FcitxUIMenu **menupp; UT_array* uimenus = FcitxInstanceGetUIMenus(instance); for (menupp = (FcitxUIMenu **) utarray_front(uimenus); menupp != NULL; menupp = (FcitxUIMenu **) utarray_next(uimenus, menupp) ) { FcitxUIMenu * menup = *menupp; if (menup->isSubMenu) continue; if (!menup->visible) continue; if (menup->candStatusBind) { FcitxUIComplexStatus* compStatus = FcitxUIGetComplexStatusByName(instance, menup->candStatusBind); if (compStatus) { if (!compStatus->visible) continue; if (GetPrivateStatus(compStatus)->avail) continue; } } FcitxMenuAddMenuItem(menu, menup->name, MENUTYPE_SUBMENU, menup); } FcitxMenuAddMenuItem(menu, NULL, MENUTYPE_DIVLINE, NULL); FcitxMenuAddMenuItem(menu, _("Configure Current Input Method"), MENUTYPE_SIMPLE, NULL); FcitxMenuAddMenuItem(menu, _("Configure"), MENUTYPE_SIMPLE, NULL); FcitxMenuAddMenuItem(menu, _("Restart"), MENUTYPE_SIMPLE, NULL); FcitxMenuAddMenuItem(menu, _("Exit"), MENUTYPE_SIMPLE, NULL); }