linux窗口透明(全局透明,进程id查找wid,进程名称查找wid)
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
程序下载地址,appimage程序,在deepin和uos上测试过
https://download.csdn.net/download/qq_43081702/16658009
参考博客
https://blog.csdn.net/nicholas_dlut/article/details/80990289 linux下C++根据进程名字获取进程的进程号PID
http://www.voidcn.com/article/p-dbqsbdxh-bsp.html linux下C++根据进程名字获取进程的进程号PID
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)