ubuntu Setforeground 前台应用切换

场景分析

有这样一个系统,一个服务主进程用于接收指令,其它服务是独立的gui 程序,服务进程根据命令将对应的gui 程序切换到前台。

windows 平台有Setforeground 这个api,可以根据进程ID,将某个应用的窗口切换到前台。ubuntu 并没有类似的api, 这里借助xdotool 这个第三方库,实现类似的功能。

xdotool git clone 后,直接make,生成动态库libxdo 和执行程序程序 xdotool。

需求

SetForeGround 大概就是根据进程ID,并激活该窗口为前台窗口。用xdotool 命令实现如下

xdotool search --pid 进程ID
#返回窗口id

xdotool windowactivate 窗口ID

 search 返回的ID 如果有多个,是因为一个进程有多个窗口,需要根据窗口标题再筛选

实际应用中,一般直接调用库,代码实现如下:

bool SetForeground(uint32_t pid, const char* window_name)
{
    Window *list = NULL;
    unsigned int nwindows;
    xdo_search_t search;
    xdo_t *context = xdo_new(NULL);

    memset(&search, 0, sizeof(xdo_search_t));
    search.max_depth = -1;
    search.require = xdo_search::SEARCH_ANY;
    search.pid = pid;
    search.searchmask = SEARCH_PID;

    do
    {
        if(list != NULL)
        {
            free(list);
        }

        xdo_search_windows(context, &search, &list, &nwindows);

        if(nwindows > 0)
        {
            for(int i = 0;i < nwindows;i++)
            {
                unsigned char *name;
                int name_len;
                int name_type;
                xdo_get_window_name(context, list[i], &name, &name_len, &name_type);
                QString window_name((char*)name);
                if(window_name == window_name)
                {
                    xdo_activate_window(context, list[i]);
                }
            }
        }

        usleep(500000);

    }while(nwindows == 0);

    if(list != NULL)
    {
        free(list);
    }
    xdo_free(context);
    return true;
}

//调用:
SetForeground(QCoreApplication::applicationPid(), this->windowTitle().toStdString().c_str());

注:这个只适用于x11 图形平台,wayland 可能存在问题。