Форум программистов, компьютерный форум, киберфорум
C/С++ под Linux
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88

Работа с библиотекой X11 (получение окон запущенных приложений)

01.02.2024, 13:41. Показов 2118. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте. Я пытаюсь написать небольшой код, который мог бы мне предоставить заголовки окон открытых программ и их скриншоты.
Мне удалось узнать, что для работы с графической обочкой используют библиотеку Xorg/X11.
Я использую ОС Kubuntu 20.04 LTS, clang++ 17.0.6 компилятор, сборщик CMake и среда разработки CLion.
Мне удалось найти очень хороший пример на https://stackoverflow.com/ques... -sendevent
Но к сожалению моя программа выдаёт ошибку когда я попробовала проверить этот код. Прилагаю вам скриншот ошибки:

Подскажите мне, пожалуйста, по ошибке? Что я не учла ?

Прилагаю и код своей программы:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <cstring>
#include <dirent.h>
#include <map>
#include <list>
#include <sstream>
#include <X11/Xlib.h>
 
/// функции для работы с окнами X11
Window *getWindowList(Display *disp, unsigned long *len) {
    Atom prop = XInternAtom(disp,"_NET_CLIENT_LIST",False), type;
    int form;
    unsigned long remain;
    unsigned char *list;
 
    if (XGetWindowProperty(disp,XDefaultRootWindow(disp),prop,0,1024,False,33,
                           &type,&form,len,&remain,&list) != Success) {  // XA_WINDOW
        return 0;
    }
 
    return (Window*)list;
}
char *getWindowName(Display *disp, Window win) {
    Atom prop = XInternAtom(disp,"WM_NAME",False), type;
    int form;
    unsigned long remain, len;
    unsigned char *list;
 
 
    if (XGetWindowProperty(disp,win,prop,0,1024,False,AnyPropertyType,
                           &type,&form,&len,&remain,&list) != Success) { // XA_STRING
 
        return NULL;
    }
 
    return (char*)list;
}
 
int main() {
 
    // теперь пройдёмся по открытым окнам в ОС
    int i;
    unsigned long len;
    XKeyEvent esend;
    Display *disp = XOpenDisplay(NULL);
    Window *list;
    char *name;
 
    list = (Window*)getWindowList(disp,&len);
    for (i=0;i<(int)len;i++) {
        name = getWindowName(disp,list[i]);
        std::cout << i << ": " << name << std::endl;
        free(name);
    }
    return 0;
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
01.02.2024, 13:41
Ответы с готовыми решениями:

Получить список окон запущенных приложений
Всем привет. Надо достать список окон запущенных приложений, как они видны в диспетчере задач. Т.е. в таком виде: Приложения (3) ...

Поочередная активация и разворачивание окон запущенных приложений
Здравствуйте, подскажите пожалуйста каким образом можно автоматизировать следующее. Пусть имеется ноутбук, с windows, на котором запущен...

Скрипт для просмотра списка окон запущенных приложений
Пожалуйста, помогите написать скрипт для составления и просмотра списка окон активных приложений. Идея такова, вызывается окно в котором...

4
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88
01.02.2024, 14:08  [ТС]
Забыла написать что я установила себе библиотеку xlib посредством команды:

Bash
1
sudo apt-get install libx11-dev xserver-xorg-dev xorg-dev
Добавлено через 18 минут
Нашла решение своей проблемы! Нужно было поправить CMakeLists.txt файл. Поправила его так:
Bash
1
2
3
4
5
6
7
8
cmake_minimum_required(VERSION 3.27)
project(HelloWorld)
 
set(CMAKE_CXX_STANDARD 17)
find_package(X11 REQUIRED)
link_libraries(${X11_LIBRARIES})
include_directories(${X11_INCLUDE_DIR})
add_executable(HelloWorld main.cpp)
Добавлено через 7 минут
У меня есть ещё вопрос. Как мне связать эти окна с запущенными процессами? Мне необходимо получить список пользовательских процессов, если у процесса есть окно, то получить заголовок окна, скриншот окна. Я получаю список процессов читая директорию /proc/
в ней я научилась найти имя и pid запущенного процесса. Может кто сможет подсказать мне как мне узнать к какому процессу относится окно? Чтобы связать их. И возможно ли получить скриншоты каждого окна или только того которое сайчас активно (стандартный скриншот экрана) ?

Есть и ещё вопрос. Как мне отфильровать процессы, мне нужно только пользовательские исключая запущенные системой. Где мне в /proc/ можно найти такую информацию ?

И ещё вопрос. У меня запущен браузер, в нем открыто несколько вкладок. Когда я получаю заголовок окна, то получаю заголовок активной вкладки. Возможно ли мне получить заголовки всех вкладок ?

Приведу полный код своей программы:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include <iostream>
#include <cstring>
#include <dirent.h>
#include <map>
#include <list>
#include <sstream>
 
#define FMT_HEADER_ONLY 
#include <fmt/format.h>
 
#include <X11/Xlib.h>
#include <X11/Xutil.h>
 
struct ProcessInfo {
    std::string Name;
    int PID;
    std::string Path;
 
    std::string ToString(){
        std::string str;
        str += fmt::format("Name: {0}\n PID: {1}",Name, PID);
        return str;
    }
};
 
std::list<ProcessInfo> listProcess = {};
 
static int is_Pid_Dir(const struct dirent* entry)
{
    const char* p;
 
    for (p = entry->d_name; *p; p++)
    {
        if (!isdigit(*p))
            return false;
    }
 
    return true;
}
 
std::map<std::string, std::string> mappify(std::string const& s)
{
    std::map<std::string, std::string> m;
 
    std::string key, val;
    std::istringstream iss(s);
 
    while(std::getline(std::getline(iss, key, ':') >> std::ws, val))
        m[key] = val;
 
    return m;
}
 
const char* paths [] = {"/proc/%s/status"};
 
ProcessInfo getInfoFromFileByPID(char pid[], const char* filename)
{
    printf("getInfoFromFileByPID param = %s %s\n", pid, filename);
 
    char            path[256];
    FILE*           fp;
    char            szFullLine[256];
    size_t          len;
    ProcessInfo     process;
 
    snprintf(path, sizeof(path), filename, pid);
    //printf("path = %s\n", path);
 
    fp = fopen(path, "r");
    if (fp)
    {
        memset(szFullLine, 0x00, sizeof(szFullLine));
        len = fread(szFullLine, sizeof(char), sizeof(szFullLine), fp);
        fclose(fp);
 
        if( len > 0 )
        {
            std::string str(szFullLine);
            std::map<std::string, std::string> map = mappify(str);
 
            if (map.find("Name") != map.end())
                process.Name = map["Name"];
            if (map.find("Pid") != map.end())
                process.PID = std::stoi(map["Pid"]);
 
            return process;
        }
    }
    return process;
}
 
/// функции для работы с окнами X11
Window *getWindowList(Display *disp, unsigned long *len) {
    Atom prop = XInternAtom(disp,"_NET_CLIENT_LIST",False), type;
    int form;
    unsigned long remain;
    unsigned char *list;
 
    if (XGetWindowProperty(disp,XDefaultRootWindow(disp),prop,0,1024,False,33,
                           &type,&form,len,&remain,&list) != Success) {  // XA_WINDOW
        return 0;
    }
 
    return (Window*)list;
}
char *getWindowName(Display *disp, Window win) {
    Atom prop = XInternAtom(disp,"WM_NAME",False), type;
    int form;
    unsigned long remain, len;
    unsigned char *list;
 
 
    if (XGetWindowProperty(disp,win,prop,0,1024,False,AnyPropertyType,
                           &type,&form,&len,&remain,&list) != Success) { // XA_STRING
 
        return NULL;
    }
 
    return (char*)list;
}
 
int main() {
    std::cout << "Hello, World!" << std::endl;
 
    DIR*            dProcPath;
    struct  dirent* entry;
 
    // Open /proc directory.
    dProcPath = opendir("/proc");
 
    if (dProcPath)
    {
        // Iterate through all files and directories of /proc.
        while ((entry = readdir(dProcPath)))
        {
            if (is_Pid_Dir(entry)) {
                for(const char* path : paths){
                    std::cout << getInfoFromFileByPID(entry->d_name,path).ToString()<<std::endl;
                }
 
            }
        }
 
    }
    closedir(dProcPath);
 
    // теперь пройдёмся по открытым окнам в ОС
    int i;
    unsigned long len;
    XKeyEvent esend;
    Display *disp = XOpenDisplay(NULL);
    Window *list;
    char *name;
 
    list = (Window*)getWindowList(disp,&len);
    for (i=0;i<(int)len;i++) {
        name = getWindowName(disp,list[i]);
        std::cout << i << ": " << name << std::endl;
        free(name);
    }
    return 0;
}
0
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88
08.02.2024, 13:03  [ТС]
Ещё раз здравствуйте. Очень нужна подсказка.
Я читаю список запущенных процессов из /proc/. И файла (status) я получаю некоторую нужную мне информацию о процессе.
Мне нужно знать идентификатор пользователя, который запустил процесс. И вот в этом файле status я вижу два интересных мне поля: uid и gid. Прочитав в интеренте я узнала, что uid это идентификатор пользователя, а gid идентификатор группы.
прошу подсказать мне как мне прочитать значение в тип uid_t ? Чтобы я могла сравнить его со значением получаемым из функции geteuid() ?
Мне нужно из списка процессов выбрать только процессы запущенные конкретным пользователем.
Вот как сейчас я читаю информацию из файла /proc/status:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
ProcessInfo getInfoFromFileByPID(char pid[], const char* filename)
{
   printf("getInfoFromFileByPID param = %s %s\n", pid, filename);
 
   char            path[256];
   FILE*           fp;
   char            szFullLine[256];
   size_t          len;
   ProcessInfo     process;
   uid_t uid       = geteuid();  // получим идентификатор текущего пользователя
 
 
   snprintf(path, sizeof(path), filename, pid);
 
   fp = fopen(path, "r");
   if (fp)
   {
       memset(szFullLine, 0x00, sizeof(szFullLine));
       len = fread(szFullLine, sizeof(char), sizeof(szFullLine), fp);
       fclose(fp);
 
 
       if( len > 0 )
       {
 
           std::string str(szFullLine);
           std::map<std::string, std::string> map = mappify(str);
 
 
           if (map.find("Name") != map.end())
               process.Name = map["Name"];
           if (map.find("Pid") != map.end())
               process.PID = std::stoi(map["Pid"]);
 
 
           std::cout << "info: " << str << std::endl;
           return process;
       }
   }
   return process;
}
т.е. я сначала считала значение файла в буфер, а потом перевожу в строку. Но как мне правильно считать uid ? Или как из строки его преобразовать в uid_t ?
0
 Аватар для Azathtot
754 / 351 / 90
Регистрация: 07.01.2023
Сообщений: 1,451
08.02.2024, 17:20
tiny developer,
вы не поверите... но uid_t это unsigned int
Если что, то char * в int это atoi()
0
0 / 0 / 1
Регистрация: 27.06.2013
Сообщений: 88
21.02.2024, 17:41  [ТС]
Здравствуйте ребята. У меня есть вопрос, и я очень надеюсь что вы не откажете мне подсказать как решить проблему.
Я работаю с библиотекой XLib. В ней есть константа Status в #define. Мне так же требуется работать со сторонней библиотекой и в ней
есть класс
C++
1
2
3
4
5
6
7
8
9
namespace sdk::events {
    class Status {
    public:
        const static inline std::string GRANTED = "GRANTED";
        const static inline std::string DENIED = "DENIED";
        const static inline std::string NOTIFY = "NOTIFY";
        const static inline std::string WARNING = "WARNING";
    };
}
Во время компиляции проекта я получаю ошибку:


Подскажите, пожалуйста, как можно решить корректно эту проблему?
Я пробовала написать так:
Название: 1.jpeg
Просмотров: 54

Размер: 3.5 Кб

но получаю ряд ошибок при работе с библиотекой XLib. Поэтому понимаю, что это не выход.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
21.02.2024, 17:41
Помогаю со студенческими работами здесь

Получение имен запущенных приложений
Написал код для получения запущенных приложений в windows. Некоторое время поработал, а потом сломался. Помогите пожалуйста Ошибка: ...

Получение caption-ов\тайтлов всех запущенных приложений
Добрый день. Нужно получить тайтлы для всех запущенных приложений, у которых они есть. Сейчас пользуюсь этим : Process.MainWindowTitle, и...

Получение координат окон сторонних приложений
Как получить массив rectangle всех окон, которые находятся на экране монитора? Или хотя бы где почитать о работе со сторонними окнами?

Иконки запущенных окон
Здравствуйте! Как получить список запущенных окон я знаю. А как вот получить их иконки? (Там у оперы - иконка буквы &quot;о&quot;,у...

Библиотека X11 и получение списка языков
Привет всем. Мне необходимо получить список языков установленных в системе. С помощью кода, который привел ниже я могу получать текущий...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка. Рецензия / Мнение/ Перевод https:/ / **********/ gallery/ thinkpad-x220-tablet-porn-gzoEAjs . . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru