예제 #1
0
QTC_EXPORT void
qtcX11ShadowInstallWithMargin(xcb_window_t win, const int margins[4])
{
    QTC_RET_IF_FAIL(win);
    if (qtcUnlikely(!margins)) {
        qtcX11ShadowInstall(win);
        return;
    }
    // In principle, I should check for _KDE_NET_WM_SHADOW in _NET_SUPPORTED.
    // However, it's complicated and we will gain nothing.
    xcb_atom_t atom = qtc_x11_kde_net_wm_shadow;
    if (qtc_disp) {
        unsigned long shadow_data[8 + 4];
        memcpy(shadow_data, shadow_data_xlib, 12 * sizeof(unsigned long));
        for (int i = 0;i < 4;i++) {
            shadow_data[i + 8] -= margins[i];
        }
        XChangeProperty(qtc_disp, win, atom, XA_CARDINAL, 32,
                        PropModeReplace, (unsigned char*)shadow_data, 12);
    } else {
        uint32_t shadow_data[8 + 4];
        memcpy(shadow_data, shadow_data_xcb, 12 * sizeof(uint32_t));
        for (int i = 0;i < 4;i++) {
            shadow_data[i + 8] -= margins[i];
        }
        qtcX11ChangeProperty(XCB_PROP_MODE_REPLACE, win, atom,
                             XCB_ATOM_CARDINAL, 32, 12, shadow_data);
        qtcX11Flush();
    }
}
예제 #2
0
파일: x11utils.c 프로젝트: Pulfer/qtcurve
QTC_EXPORT void
qtcX11MapRaised(xcb_window_t win)
{
    if (qtcUnlikely(!win))
        return;
    static const uint32_t val = XCB_STACK_MODE_ABOVE;
    qtcX11CallVoid(configure_window, win, XCB_CONFIG_WINDOW_STACK_MODE, &val);
    qtcX11CallVoid(map_window, win);
}
예제 #3
0
파일: x11utils.c 프로젝트: Pulfer/qtcurve
QTC_EXPORT void
qtcX11InitXlib(Display *disp)
{
    if (qtcUnlikely(qtc_xcb_conn) || !disp) {
        return;
    }
    qtc_disp = disp;
    qtcX11InitXcb(XGetXCBConnection(disp), DefaultScreen(disp));
}
예제 #4
0
파일: x11utils.c 프로젝트: Pulfer/qtcurve
QTC_EXPORT xcb_screen_t*
(qtcX11GetScreen)(int screen_no)
{
    if (screen_no == -1 || screen_no == qtc_default_screen_no) {
        return qtc_default_screen;
    }
    if (qtcUnlikely(!qtc_xcb_conn)) {
        return NULL;
    }
    return screen_of_display(qtc_xcb_conn, screen_no);
}
예제 #5
0
파일: strs.cpp 프로젝트: KDE/qtcurve
QTC_EXPORT void
_forEach(const char *str, char delim, char escape,
         const std::function<bool(const char*, size_t)> &func)
{
    QTC_RET_IF_FAIL(str);
    Str::Buff<1024> buff;
    if (qtcUnlikely(escape == delim)) {
        escape = '\0';
    }
    const char key[] = {delim, escape, '\0'};
    const char *p = str;
    while (true) {
        size_t len = 0;
        while (true) {
            size_t sub_len = strcspn(p, key);
            buff.resize(len + sub_len + 2);
            memcpy(buff.get() + len, p, sub_len);
            len += sub_len;
            p += sub_len;
            if (escape && *p == escape) {
                buff[len] = p[1];
                if (qtcUnlikely(!p[1])) {
                    p++;
                    break;
                }
                len++;
                p += 2;
            } else {
                buff[len] = '\0';
                break;
            }
        }
        if (!func(buff.get(), len) || !*p) {
            break;
        }
        p++;
    }
}
예제 #6
0
파일: x11utils.c 프로젝트: Pulfer/qtcurve
QTC_EXPORT bool
qtcX11IsEmbed(xcb_window_t win)
{
    if (qtcUnlikely(!win))
        return false;
    xcb_atom_t xembed_atom = qtc_x11_atoms[QTC_X11_ATOM_XEMBED_INFO];
    xcb_get_property_reply_t *reply =
        qtcX11Call(get_property, 0, win, xembed_atom,
                   xembed_atom, 0, 1);
    if (!reply) {
        return false;
    }
    bool res = xcb_get_property_value_length(reply) > 0;
    free(reply);
    return res;
}
예제 #7
0
파일: process.c 프로젝트: Kermit/qtcurve
QTC_EXPORT bool
qtcPopen(const char *file, const char *const *argv,
         unsigned fd_num, QtcPopenFD *fds)
{
    if (qtcUnlikely(!fds || !fd_num)) {
        return qtcSpawn(file, argv, NULL, NULL);
    }
    for (unsigned i = 0;i < fd_num;i++) {
        QTC_RET_IF_FAIL(fds[i].orig >= 0, false);
    }
    int socket_fds[2];
    QTC_RET_IF_FAIL(socketpair(AF_UNIX, SOCK_STREAM, 0,
                               socket_fds) == 0, false);
    qtcFDSetCloexec(socket_fds[0], true);
    qtcFDSetCloexec(socket_fds[1], true);
    QtcPopenData cbdata = {socket_fds[0], fd_num, fds};
    bool res = qtcSpawn(file, argv, qtcPopenCb, &cbdata, qtcPopenFailCb);
    if (!res) {
        shutdown(socket_fds[0], SHUT_RDWR);
        close(socket_fds[0]);
        shutdown(socket_fds[1], SHUT_RDWR);
        close(socket_fds[1]);
        return false;
    }
    close(socket_fds[0]);
    for (unsigned i = 0;i < fd_num;i++) {
        if ((fds[i].replace = qtcRecvFD(socket_fds[1])) < 0) {
            res = false;
            for (unsigned j = 0;j < i;j++) {
                if (fds[i].replace) {
                    shutdown(fds[i].replace, SHUT_RDWR);
                    close(fds[i].replace);
                }
            }
            break;
        }
        if (!(fds[i].mode & (QTC_POPEN_READ | QTC_POPEN_WRITE))) {
            close(fds[i].replace);
            fds[i].replace = -1;
            continue;
        }
    }
    shutdown(socket_fds[1], SHUT_RDWR);
    close(socket_fds[1]);
    return res;
}
예제 #8
0
파일: x11utils.c 프로젝트: Pulfer/qtcurve
QTC_EXPORT bool
qtcX11HasAlpha(xcb_window_t win)
{
    if (qtcUnlikely(!win))
        return false;
    if (!qtcX11CompositingActive()) {
        return false;
    }
    if (!win) {
        return true;
    }
    xcb_get_geometry_reply_t *reply = qtcX11Call(get_geometry, win);
    if (!reply) {
        return false;
    }
    bool res = (reply->depth == 32);
    free(reply);
    return res;
}
예제 #9
0
파일: x11utils.c 프로젝트: Pulfer/qtcurve
QTC_EXPORT int32_t
qtcX11GetShortProp(xcb_window_t win, xcb_atom_t atom)
{
    if (qtcUnlikely(!win))
        return -1;
    int32_t res = -1;
    xcb_get_property_reply_t *reply =
        qtcX11Call(get_property, 0, win, atom, XCB_ATOM_CARDINAL, 0, 1);
    if (!reply) {
        return -1;
    }
    if (xcb_get_property_value_length(reply) > 0) {
        uint32_t val = *(int32_t*)xcb_get_property_value(reply);
        if (val < 512) {
            res = val;
        }
    }
    free(reply);
    return res;
}
예제 #10
0
파일: x11utils.c 프로젝트: Pulfer/qtcurve
QTC_EXPORT void
qtcX11InitXcb(xcb_connection_t *conn, int screen_no)
{
    if (qtcUnlikely(qtc_xcb_conn) || !conn) {
        return;
    }
    if (screen_no < 0) {
        screen_no = 0;
    }
    qtc_xcb_conn = conn;
    qtc_default_screen_no = screen_no;
    qtc_default_screen = screen_of_display(conn, screen_no);
    if (qtc_default_screen) {
        qtc_root_window = qtc_default_screen->root;
    }
    const size_t base_len = strlen("_NET_WM_CM_S");
    sprintf(wm_cm_s_atom_name + base_len, "%d", screen_no);
    qtcX11GetAtoms(_QTC_X11_ATOM_NUMBER, qtc_x11_atoms,
                   qtc_x11_atom_names, true);
    qtcX11ShadowInit();
}
예제 #11
0
파일: x11utils.c 프로젝트: Pulfer/qtcurve
QTC_EXPORT void
qtcX11GetAtoms(size_t n, xcb_atom_t *atoms, const char *const names[],
               bool create)
{
    xcb_connection_t *conn = qtc_xcb_conn;
    memset(atoms, 0, sizeof(xcb_atom_t) * n);
    if (qtcUnlikely(!conn)) {
        return;
    }
    xcb_intern_atom_cookie_t cookies[n];
    for (size_t i = 0;i < n;i++) {
        cookies[i] = xcb_intern_atom(conn, !create,
                                     strlen(names[i]), names[i]);
    }
    for (size_t i = 0;i < n;i++) {
        xcb_intern_atom_reply_t *r =
            xcb_intern_atom_reply(conn, cookies[i], 0);
        if (r) {
            atoms[i] = r->atom;
            free(r);
        }
    }
}
예제 #12
0
파일: process.c 프로젝트: Kermit/qtcurve
QTC_EXPORT bool
qtcPopenBuff(const char *file, const char *const argv[],
             unsigned buff_num, QtcPopenBuff *buffs, int timeout)
{
    if (qtcUnlikely(!buffs || !buff_num)) {
        return qtcSpawn(file, argv, NULL, NULL);
    }
    bool need_poll = false;
    for (unsigned i = 0;i < buff_num;i++) {
        QTC_RET_IF_FAIL(buffs[i].orig >= 0, false);
        QTC_RET_IF_FAIL(!(buffs[i].mode & QTC_POPEN_READ &&
                          buffs[i].mode & QTC_POPEN_WRITE), false);
        if (buffs[i].mode & QTC_POPEN_READ ||
            buffs[i].mode & QTC_POPEN_WRITE) {
            need_poll = true;
        }
    }
    QTC_DEF_LOCAL_BUFF(QtcPopenFD, fds, 16, buff_num);
    for (unsigned i = 0;i < buff_num;i++) {
        fds.p[i].orig = buffs[i].orig;
        fds.p[i].replace = -1;
        fds.p[i].mode = buffs[i].mode;
    }
    bool res = qtcPopen(file, argv, buff_num, fds.p);
    if (!res) {
        QTC_FREE_LOCAL_BUFF(fds);
        return false;
    }
    for (unsigned i = 0;i < buff_num;i++) {
        buffs[i].orig = fds.p[i].replace;
        if (fds.p[i].replace >= 0) {
            qtcFDSetNonBlock(fds.p[i].replace, true);
            qtcFDSetCloexec(fds.p[i].replace, true);
        }
    }
    QTC_FREE_LOCAL_BUFF(fds);
    if (!need_poll) {
        return true;
    }
    QTC_DEF_LOCAL_BUFF(struct pollfd, poll_fds, 16, buff_num);
    QTC_DEF_LOCAL_BUFF(int, indexes, 16, buff_num);
    unsigned poll_fd_num = 0;
    for (unsigned i = 0;i < buff_num;i++) {
        if (!(buffs[i].mode & (QTC_POPEN_READ | QTC_POPEN_WRITE))) {
            close(buffs[i].orig);
            continue;
        }
        indexes.p[poll_fd_num] = i;
        struct pollfd *cur_fd = &poll_fds.p[poll_fd_num];
        cur_fd->fd = buffs[i].orig;
        cur_fd->events = (buffs[i].mode & QTC_POPEN_READ) ? POLLIN : POLLOUT;
        poll_fd_num++;
    }
    uint64_t start_time = qtcGetTime();
    int poll_timeout = timeout;
    while (true) {
        int ret = poll(poll_fds.p, poll_fd_num, poll_timeout);
        if (ret == -1) {
            if (errno == EINTR) {
                if (!qtcPopenPollCheckTimeout(start_time, timeout,
                                              &poll_timeout)) {
                    break;
                }
                continue;
            }
            break;
        } else if (ret == 0) {
            break;
        }
        for (unsigned i = 0;i < poll_fd_num;i++) {
            struct pollfd *cur_fd = &poll_fds.p[i];
            if (cur_fd->revents & POLLIN) {
                if (!qtcPopenReadBuff(&buffs[indexes.p[i]])) {
                    cur_fd->events &= ~POLLIN;
                }
            } else if (cur_fd->revents & POLLOUT) {
                if (!qtcPopenWriteBuff(&buffs[indexes.p[i]])) {
                    cur_fd->events &= ~POLLOUT;
                }
            }
            if (cur_fd->revents & (POLLERR | POLLHUP | POLLNVAL) ||
                !(cur_fd->events & (POLLIN | POLLOUT))) {
                shutdown(cur_fd->fd, SHUT_RDWR);
                close(cur_fd->fd);
                poll_fd_num--;
                memmove(cur_fd, cur_fd + 1,
                        (poll_fd_num - i) * sizeof(struct pollfd));
                memmove(indexes.p + i, indexes.p + i + 1,
                        (poll_fd_num - i) * sizeof(int));
                i--;
            }
        }
        if (poll_fd_num <= 0 || !qtcPopenPollCheckTimeout(start_time, timeout,
                                                          &poll_timeout)) {
            break;
        }
    }
    for (unsigned i = 0;i < poll_fd_num;i++) {
        struct pollfd *cur_fd = &poll_fds.p[i];
        shutdown(cur_fd->fd, SHUT_RDWR);
        close(cur_fd->fd);
    }
    QTC_FREE_LOCAL_BUFF(indexes);
    QTC_FREE_LOCAL_BUFF(poll_fds);
    return true;
}