linux窗口透明(全局透明,进程id查找wid,进程名称查找wid)

17 篇文章 2 订阅
10 篇文章 0 订阅

linux窗口透明

使用到了qt xcb-ewmh x11-xcb

效果图

在这里插入图片描述

如何实现

控制全部窗口透明
1.遍历WID树,的到全部窗口得wid
2.区别窗口属性,桌面和dock窗口不设置透明,其他窗口设置透明(透明度随着滑动条)
3.监听x11时间,新的窗口创建就设置透明度感觉话滑动条

核心代码 通过名称找到该程序的wid

#ifndef SETDESKTOP_H
#define SETDESKTOP_H

// Attempt to identify a window by name or attribute.
// by Adam Pierce <adam@doctort.org>

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <iostream>
#include <list>
#include <stdlib.h>

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>

int find_pid_by_name(char *ProcName, int *foundpid)
{
    DIR             *dir;
    struct dirent   *d;
    int             pid, i;
    char            *s;
    int pnlen;

    i = 0;
    foundpid[0] = 0;
    pnlen = strlen(ProcName);

    /* Open the /proc directory. */
    dir = opendir("/proc");
    if (!dir) {
        printf("cannot open /proc");
        return -1;
    }

    /* Walk through the directory. */
    while ((d = readdir(dir)) != NULL) {

        char exe [PATH_MAX + 1];
        char path[PATH_MAX + 1];
        int len;
        int namelen;

        /* See if this is a process */
        if ((pid = atoi(d->d_name)) == 0)       continue;

        snprintf(exe, sizeof(exe), "/proc/%s/exe", d->d_name);
        if ((len = readlink(exe, path, PATH_MAX)) < 0)
            continue;
        path[len] = '\0';

        /* Find ProcName */
        s = strrchr(path, '/');
        if (s == NULL) continue;
        s++;

        /* we don't need small name len */
        namelen = strlen(s);
        if (namelen < pnlen)     continue;

        if (!strncmp(ProcName, s, pnlen)) {
            /* to avoid subname like search proc tao but proc taolinke matched */
            if (s[pnlen] == ' ' || s[pnlen] == '\0') {
                foundpid[i] = pid;
                i++;
            }
        }
    }

    foundpid[i] = 0;
    closedir(dir);

    return  0;

}


using namespace std;

class WindowsMatchingPid
{
public:
    WindowsMatchingPid(Display *display, Window wRoot, unsigned long pid)
        : _display(display)
        , _pid(pid)
    {
        // Get the PID property atom.
        _atomPID = XInternAtom(display, "_NET_WM_PID", True);
        if (_atomPID == None) {
            cout << "No such atom" << endl;
            return;
        }

        search(wRoot);
    }

    const list<Window> &result() const { return _result; }

    const list<Window> &Allresult() const { return _allResult; }

private:
    unsigned long  _pid;
    Atom           _atomPID;
    Display       *_display;
    list<Window>   _result;
    list<Window>   _allResult;
    void search(Window w)
    {
        // Get the PID for the current Window.
        Atom           type;
        int            format;
        unsigned long  nItems;
        unsigned long  bytesAfter;
        unsigned char *propPID = 0;
        if (Success == XGetWindowProperty(_display, w, _atomPID, 0, 1, False, XA_CARDINAL,
                                          &type, &format, &nItems, &bytesAfter, &propPID)) {
            if (propPID != 0) {
                // If the PID matches, add this window to the result set.
                if (_pid == *((unsigned long *)propPID))
                    _result.push_back(w);

                XFree(propPID);
            }
        }

        // Recurse into child windows.
        Window    wRoot;
        Window    wParent;
        Window   *wChild;
        unsigned  nChildren;
        if (0 != XQueryTree(_display, w, &wRoot, &wParent, &wChild, &nChildren)) {
            for (unsigned i = 0; i < nChildren; i++) {
                search(wChild[i]);
                _allResult.push_back(wChild[i]);
            }
        }
    }
};
#endif // SETDESKTOP_H

//通过名称寻找改名称的wid的list
QList<unsigned long> MainWindow::searchWindowid(const QString &name)
{
    QList<Window> wlist;

    char *str = NULL;
    QByteArray ba = name.toLatin1();
    str = (char *)malloc(ba.length() + 1);
    memset(str, 0, ba.length());
    memcpy(str, ba.data(), ba.length());

    str[ba.length()] = '\0';
    //设置desktop透明
    int pid_t[128];
    find_pid_by_name(str, pid_t);
    int pid = pid_t[0];


    Display *display = XOpenDisplay(0);
    WindowsMatchingPid match(display, XDefaultRootWindow(display), pid);
    const list<Window> &result = match.result();
    for (Window id : result) {
        wlist.push_back(id);
    }
    return wlist;
}

通过wid查找窗口属性{我这里是为了判断是否是desktop和dock属性}

//初始化

    xcb_ewmh_connection_t m_ewmh_connection;
    xcb_intern_atom_cookie_t *m_cookie{nullptr};

    m_cookie  = xcb_ewmh_init_atoms(QX11Info::connection(), &m_ewmh_connection);
    xcb_ewmh_init_atoms_replies(&m_ewmh_connection, m_cookie, NULL);
//传入wid,输出type

    uint32_t searchWindowType(int wid)
{
    uint32_t reId = 0;
    if (m_cookie) {

        xcb_get_property_cookie_t cooke = xcb_ewmh_get_wm_window_type(&m_ewmh_connection, wid);

        xcb_ewmh_get_atoms_reply_t name;
        xcb_generic_error_t *error_t = new xcb_generic_error_t;
//        xcb_ewmh_get_wm_window_type_reply(&m_ewmh_connection, cooke, &name, NULL);
        xcb_ewmh_get_wm_window_type_reply(&m_ewmh_connection, cooke, &name, &error_t);
        qDebug() << "ssss";
        if (error_t) {
            qDebug() << error_t->response_type;
            qDebug() << error_t->error_code;
            qDebug() << error_t->sequence;
            qDebug() << error_t->resource_id;
            qDebug() << error_t->minor_code;
            qDebug() << error_t->major_code;
            delete error_t;
            error_t = NULL;
            return 0;
        } else {

        }
        qDebug() << "eeee";
        if (name.atoms && name.atoms_len <= 10) {
            reId = name.atoms[0];
        }

    }
    return reId;
}

通过 wid转化为QWindow,并设置透明度(获取全部窗口)

void MainWindow::setAllWindows()
{
    qDebug() << "xxx1";
    char *str = NULL;
    QByteArray ba = "";
    str = (char *)malloc(ba.length() + 1);
    memset(str, 0, ba.length());
    memcpy(str, ba.data(), ba.length());
    qDebug() << "xxxx2";
    str[ba.length()] = '\0';
    //设置desktop透明
    int pid_t[128];
    find_pid_by_name(str, pid_t);
    int pid = pid_t[0];

    qDebug() << "xxxx3";
    Display *display = XOpenDisplay(0);
    WindowsMatchingPid match(display, XDefaultRootWindow(display), pid);
//    const list<Window> &result = match.result();
//获得全部窗口wid
    const list<Window> &allresult = match.Allresult();
    qDebug() << "xxxx4";
    for (Window id : allresult) {
        QWindow *window = QWindow::fromWinId((unsigned long)id);
        uint32_t indexId = searchWindowType(id) ;

        qDebug() << indexId;
		//373和374一般都为desktop和dock
        if (window != nullptr && !m_noOpacityId.contains(id)
                && (indexId != 373 || indexId == 374)) {

			//滑动条的值,这里可以自定义
            int value = ui->opacitySlider->value();
            double a = (double)value;
            double o = a / 100.0;
            window->setOpacity(o);
            static int i = 0;
            qDebug() << "ok" << i++;
            strucWindow st;
            st.window = window;
            st.wid = id;
            st.name = "name";
            st.opacity = o;
            m_windowVec.insert(id, st);

        }
    }
}

代码地址:

https://github.com/dependon/x11opacitytool

参考博客

https://blog.csdn.net/nicholas_dlut/article/details/80990289 linux下C++根据进程名字获取进程的进程号PID
http://www.voidcn.com/article/p-dbqsbdxh-bsp.html linux下C++根据进程名字获取进程的进程号PID

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏有凉风,冬有雪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值