hanxi / blog

涵曦的博客
https://blog.hanxi.cc
56 stars 5 forks source link

cocos2dx v3 添加 Linux 下的 EditBox #7

Open hanxi opened 9 years ago

hanxi commented 9 years ago

1. 调用其他输入框程序实现

调用 zenity 实现,使用 popen 系统调用,参考:tinyfiledialogs 的实现。

zenity 的文本输入框介绍在这里

实现已经放到评论区:https://github.com/hanxi/blog/issues/7#issuecomment-109287336

2. 最后采用了 GTK+ 的 dialog 实现

这种实现更像 windows 下的 dialog。而且查了 glfwFAQ,建议使用 GTK+ 实现 messge box。

需要安装 gtk 库:sudo apt-get install libgtk-3-dev

主要代码是参考这里的。还添加了下面两点:

gtk_window_set_keep_above(GTK_WINDOW(dialog), true);
// desoty dialog when lost focus
static void dialogFocusOutCallback(GtkWidget* widget, gpointer user_data)
{
    gtk_widget_destroy(widget);
}

...
g_signal_connect(dialog, "focus-out-event", G_CALLBACK(dialogFocusOutCallback), NULL);

我也是试过去找到 dialog 的父窗口,然后设置模态等等,使 dialog 为子窗口。可是没能成功的实现。现在我的这种实现也能满足基本的需求,代码在这里:https://github.com/cocos2d/cocos2d-x/pull/12220

hanxi commented 9 years ago

采用 zentiy 实现的源码


#define MAX_LINE 1024
#define MAX_TEXT 4096 
static bool detectEnvironment(std::string env) {
    char buf[MAX_LINE];
    std::string command = "which " + env;
    bool found = false;
    FILE *f = NULL;

    f = popen(command.c_str(), "r");
    found = (fgets(buf, sizeof(buf), f) != NULL && !strchr(buf, ':'));
    pclose(f);
    return found;
}

void EditBoxImplLinux::openKeyboard()
{
    if (_delegate != NULL)
    {
        _delegate->editBoxEditingDidBegin(_editBox);
    }

#if CC_ENABLE_SCRIPT_BINDING
    EditBox* pEditBox = this->getEditBox();
    if (NULL != pEditBox && 0 != pEditBox->getScriptEditBoxHandler())
    {
        CommonScriptData data(pEditBox->getScriptEditBoxHandler(), "began",pEditBox);
        ScriptEvent event(cocos2d::kCommonEvent,(void*)&data);
        ScriptEngineManager::getInstance()->getScriptEngine()->sendEvent(&event);
    }
#endif

    bool found = detectEnvironment("zenity");
    CC_ASSERT(found && "You need install zenity to use EditBox in linux.");
    FILE *f = NULL;
    char buf[MAX_TEXT];
    char *p;

    std::string command = "zenity --entry --title='EditBox' --text='EditBox' ";
    std::string entryText = _text;
    if (_placeHolder.length() > 0 && _text.length() == 0)
    {
        entryText = _placeHolder;
    }
    command += "--entry-text='" + entryText + "' ";

    if (EditBox::InputFlag::PASSWORD == _editBoxInputFlag)
    {
        command += "--hide-text";
    }

    if (!(f = popen(command.c_str(), "r")))
    {
        CCLOG("ERROR in popen : %s ", command.c_str());
    }

    buf[0] = '\0';
    p = buf;
    if (fgets(p, MAX_TEXT, f) != NULL)
    {
        *(p + strlen(p) - 1) = '\0';
        CCLOG("EditBox input : %s ", p);
        editBoxCallbackFunc(p, this);
    }
    pclose(f);
    return;
}