C 是否有与SetWindowPos相同的Linux版本?

C 是否有与SetWindowPos相同的Linux版本?,c,linux,windows,C,Linux,Windows,不久前,我用C编写了一个脚本,它使用Windows API函数EnumWindows、SetWindowPos和SetForeGroundIndow自动将窗口(按标题)安排在我通常需要的特定布局中 这些函数是否有Linux等价物?我将使用Kubuntu,因此特定于KDE和/或Ubuntu的解决方案很好。是的,您可以使用X Windows协议来实现这一点。这是一个非常低级的协议,因此需要做一些工作。您可以使用xcb\u query\u tree查找要操作的窗口,然后使用xcb\u configur

不久前,我用C编写了一个脚本,它使用Windows API函数EnumWindows、SetWindowPos和SetForeGroundIndow自动将窗口(按标题)安排在我通常需要的特定布局中


这些函数是否有Linux等价物?我将使用Kubuntu,因此特定于KDE和/或Ubuntu的解决方案很好。

是的,您可以使用X Windows协议来实现这一点。这是一个非常低级的协议,因此需要做一些工作。您可以使用
xcb\u query\u tree
查找要操作的窗口,然后使用
xcb\u configure\u window
移动它。提供有关如何执行此操作的一些详细信息。使用这些函数所来自的库是有困难的,但是你可能想用谷歌搜索一个更好的库

这可能看起来令人望而生畏,但也不算太糟糕。这是一个50行C程序,它将把所有xterms 10px移到右边:

#include <stdio.h>
#include <string.h>
#include <xcb/xcb.h>

void handle(xcb_connection_t* connection, xcb_window_t window) {

    xcb_query_tree_reply_t *tree = xcb_query_tree_reply(connection,
        xcb_query_tree(connection, window), NULL);
    xcb_window_t *children = xcb_query_tree_children(tree);

    for (int i = 0;  i < xcb_query_tree_children_length(tree); i++) {

        xcb_get_property_reply_t *class_reply = xcb_get_property_reply(
            connection,
            xcb_get_property(connection, 0, children[i], XCB_ATOM_WM_CLASS,
                XCB_ATOM_STRING, 0, 512), NULL);
        char* class = (char*)xcb_get_property_value(class_reply);
        class[xcb_get_property_value_length(class_reply)] = '\0';

        if (!strcmp(class, "xterm")) {
            /* Get geometry relative to parent window */
            xcb_get_geometry_reply_t* geom = xcb_get_geometry_reply(
                connection,
                xcb_get_geometry(connection, window),
                NULL);

            /* Move 10 pixels right */
            uint32_t values[] = {geom->x + 10};
            xcb_configure_window(connection, children[i],
                XCB_CONFIG_WINDOW_X, values);
        }

        /* Recurse down window tree */
        handle(connection, children[i]);
    }
}

int main() {
    xcb_connection_t *connection;
    const xcb_setup_t *setup;

    connection = xcb_connect(NULL, NULL);
    setup = xcb_get_setup(connection);
    xcb_screen_iterator_t screen = xcb_setup_roots_iterator(setup);
    handle(connection, screen.data->root);

    return 0;
}
#包括
#包括
#包括
无效句柄(xcb_连接\u t*连接,xcb_窗口\u t窗口){
xcb_查询树回复树=xcb_查询树回复(连接,
xcb_查询_树(连接,窗口),NULL);
xcb_window_t*children=xcb_query_tree_children(树);
对于(int i=0;ix+10};
xcb_配置_窗口(连接,子项[i],
XCB_配置_窗口_X,值);
}
/*向下递归窗口树*/
句柄(连接,子类[i]);
}
}
int main(){
xcb_连接\u t*连接;
常数xcb_设置_t*设置;
连接=xcb_connect(NULL,NULL);
设置=xcb\u获取\u设置(连接);
xcb\u screen\u iterator\u t screen=xcb\u setup\u root\u iterator(setup);
句柄(连接,screen.data->root);
返回0;
}

没有错误检查或内存管理,它所能做的也非常有限。但是更新成一个你想要的程序应该很简单,或者通过添加命令行选项来指定要在哪些窗口上操作以及要在这些窗口上执行哪些操作,从而将其转换为通用帮助程序。

@andrewdotn有一个很好的答案,但您也可以通过使用XQueryTree和使用XFetchName获取窗口名,然后使用XMoveWindow移动它。下面的示例将列出所有窗口,如果有被称为“xeyes”的窗口,它们将移动到左上角。与大多数X程序一样,它还有更多的功能,这可能需要调用XGetWindowProperty来获取_NET_WM_NAME扩展窗口管理器属性,但该示例可以作为启动程序使用。使用gcc-Wall-g-o demo.c-lX11编译

#include <X11/Xlib.h>
#include <stdio.h>
#include <string.h>

static int
EnumWindows(Display *display, Window window, int depth)
{
    Window parent, *children;
    unsigned int count = 0;
    int r = 1, n = 0;
    char *name = NULL;

    XFetchName(display, window, &name);
    for (n = 0; n < depth; ++n) putchar(' ');
    printf("%08x %s\n", (int)window, name?name:"(null)");
    if (name && strcmp("xeyes", name) == 0) {
        XMoveWindow(display, window, 5, 5);
    }
    if (name) XFree(name);

    if (XQueryTree(display, window, &window, &parent, &children, &count) == 0) {
        fprintf(stderr, "error: XQueryTree error\n");
        return 0;
    }
    for (n = 0; r && n < count; ++n) {
        r = EnumWindows(display, children[n], depth+1);
    }
    XFree(children);
    return r;
}

int
main(int argc, char *const argv[])
{
    Display *display = NULL;

    if ((display = XOpenDisplay(NULL)) == NULL) {
        fprintf(stderr, "error: cannot connect to X server\n");
        return 1;
    }

    EnumWindows(display, DefaultRootWindow(display), 0);
    XCloseDisplay(display);
    return 0;
}
#包括
#包括
#包括
静态整数
枚举窗口(显示*显示,窗口窗口,整数深度)
{
窗口父项,*子项;
无符号整数计数=0;
int r=1,n=0;
char*name=NULL;
XFetchName(显示、窗口和名称);
对于(n=0;n
最好的方法是使用窗口管理器本身(如果您的窗口管理器支持扩展),或者使用设计用于支持“寻呼机”的协议和提示(寻呼机=执行窗口组织或导航操作的任何非窗口管理器进程)

EWMH规范包括一个为寻呼机设计的_NET_MOVERESIZE_窗口

原始Xlib或Xcb相当粗糙,但有一个名为libwnck的库专门设计用于完成您所谈论的这类事情。(我很久以前就编写了原始库,但它一直由其他人维护。)即使你不使用它,也要阅读代码,看看如何操作。我不确定KDE是否有与KDE风格的API相当的API

应该没有必要使用任何KDE、GNOME或特定于发行版的东西,因为所需的东西都在EWMH中详细说明了。这就是说,对于某些窗口管理器来说,将其作为扩展可能比编写单独的应用程序更容易


直接使用老式的X电话当然可以奏效,但在我看来,如果你想解决所有的bug和死角问题,有很多细节需要处理,需要大量的专业知识,因此,使用WM扩展API或寻呼机库将是我的建议。

因为您似乎不是专门在代码中寻找解决方案,而是在桌面环境中,您需要看看在这样的桌面环境中处理窗口放置的窗口管理器之一

  • <