added windowID.cpp, trying to make elog mechanism better

This commit is contained in:
Ryan Tang 2023-02-17 19:30:31 -05:00
parent 78330049ed
commit 36b871802d
9 changed files with 323 additions and 56 deletions

2
.gitignore vendored
View File

@ -4,6 +4,8 @@ SOLARIS_DAQ
*.sol *.sol
programSettings.txt programSettings.txt
test test
windowID
screenshot.*
*~ *~
*.autosave *.autosave

View File

@ -5,7 +5,7 @@
"includePath": [ "includePath": [
"${workspaceFolder}/**", "${workspaceFolder}/**",
"/usr/include/x86_64-linux-gnu/qt6/**", "/usr/include/x86_64-linux-gnu/qt6/**",
"/opt/root/include/*" "/opt/root/include/**"
], ],
"defines": [], "defines": [],
"compilerPath": "/usr/bin/gcc", "compilerPath": "/usr/bin/gcc",

View File

@ -8,7 +8,7 @@ INCLUDEPATH += .
QT += widgets charts QT += widgets charts
LIBS += -lcurl -lCAEN_FELib LIBS += -lcurl -lCAEN_FELib -lX11
# You can make your code fail to compile if you use deprecated APIs. # You can make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line. # In order to do so, uncomment the following line.

View File

@ -15,6 +15,11 @@
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QApplication> #include <QApplication>
#include <QDateTime> #include <QDateTime>
#include <QProcess>
#include <QScreen>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <unistd.h> #include <unistd.h>
@ -33,6 +38,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){
influx = NULL; influx = NULL;
readDataThread = NULL; readDataThread = NULL;
scope = NULL; scope = NULL;
runTimer = new QTimer();
connect(runTimer, &QTimer::timeout, this, &MainWindow::AutoRun);
{ {
scalar = new QMainWindow(this); scalar = new QMainWindow(this);
@ -69,10 +76,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){
QGridLayout * layout1 = new QGridLayout(box1); QGridLayout * layout1 = new QGridLayout(box1);
bnProgramSettings = new QPushButton("Program Settings", this); bnProgramSettings = new QPushButton("Program Settings", this);
connect(bnProgramSettings, &QPushButton::clicked, this, &MainWindow::ProgramSettings); connect(bnProgramSettings, &QPushButton::clicked, this, &MainWindow::ProgramSettingsPanel);
bnNewExp = new QPushButton("New/Change/Reload Exp", this); bnNewExp = new QPushButton("New/Change/Reload Exp", this);
connect(bnNewExp, &QPushButton::clicked, this, &MainWindow::SetupNewExp); connect(bnNewExp, &QPushButton::clicked, this, &MainWindow::SetupNewExpPanel);
QLabel * lExpName = new QLabel("Exp Name ", this); QLabel * lExpName = new QLabel("Exp Name ", this);
lExpName->setAlignment(Qt::AlignRight | Qt::AlignCenter); lExpName->setAlignment(Qt::AlignRight | Qt::AlignCenter);
@ -107,10 +114,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){
layout1->addWidget(lExpName, 0, 2); layout1->addWidget(lExpName, 0, 2);
layout1->addWidget(leExpName, 0, 3); layout1->addWidget(leExpName, 0, 3);
layout1->addWidget(bnOpenScope, 1, 0);
layout1->addWidget(bnOpenDigitizers, 1, 1); layout1->addWidget(bnOpenDigitizers, 1, 1);
layout1->addWidget(bnCloseDigitizers, 1, 2, 1, 2); layout1->addWidget(bnCloseDigitizers, 1, 2, 1, 2);
layout1->addWidget(bnOpenScope, 2, 0);
layout1->addWidget(bnDigiSettings, 2, 1); layout1->addWidget(bnDigiSettings, 2, 1);
layout1->addWidget(bnSOLSettings, 2, 2, 1, 2); layout1->addWidget(bnSOLSettings, 2, 2, 1, 2);
@ -152,12 +159,17 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){
chkSaveRun->setEnabled(false); chkSaveRun->setEnabled(false);
cbAutoRun = new QComboBox(this); cbAutoRun = new QComboBox(this);
cbAutoRun->addItem("Single Run"); cbAutoRun->addItem("Single infinte", -1);
cbAutoRun->addItem("Auto 30 mins"); cbAutoRun->addItem("Single 30 mins", 30);
cbAutoRun->addItem("Auto 60 mins"); cbAutoRun->addItem("Single 60 mins", 60);
cbAutoRun->addItem("Auto 2 hrs"); cbAutoRun->addItem("Single 2 hrs", 120);
cbAutoRun->addItem("Auto 3 hrs"); cbAutoRun->addItem("Single 3 hrs", 180);
cbAutoRun->addItem("Auto 5 hrs"); cbAutoRun->addItem("Single 5 hrs", 300);
cbAutoRun->addItem("Every 30 mins", -30);
cbAutoRun->addItem("Every 60 mins", -60);
cbAutoRun->addItem("Every 2 hrs", -120);
cbAutoRun->addItem("Every 3 hrs", -180);
cbAutoRun->addItem("Every 5 hrs", -300);
cbAutoRun->setEnabled(false); cbAutoRun->setEnabled(false);
bnStartACQ = new QPushButton("Start ACQ", this); bnStartACQ = new QPushButton("Start ACQ", this);
@ -218,7 +230,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){
LogMsg("<font style=\"color: blue;\"><b>Welcome to SOLARIS DAQ.</b></font>"); LogMsg("<font style=\"color: blue;\"><b>Welcome to SOLARIS DAQ.</b></font>");
if( OpenProgramSettings() ) OpenExpSettings(); if( LoadProgramSettings() ) LoadExpSettings();
} }
@ -233,8 +245,10 @@ MainWindow::~MainWindow(){
//delete logInfo; //delete logInfo;
printf("- %s\n", __func__); printf("- %s\n", __func__);
for( int i = 0; i < nDigi ; i++){ if( digi ){
if( readDataThread[i]->isRunning()) StopACQ(); for( int i = 0; i < nDigi ; i++){
if( readDataThread[i]->isRunning()) StopACQ();
}
} }
DeleteTriggerLineEdit(); DeleteTriggerLineEdit();
@ -257,35 +271,37 @@ void MainWindow::StartACQ(){
LogMsg("=========================== Start <b><font style=\"color : red;\">Run-" + runIDStr + "</font></b>"); LogMsg("=========================== Start <b><font style=\"color : red;\">Run-" + runIDStr + "</font></b>");
//============ start comment //============ start comment
QDialog * dOpen = new QDialog(this); //if( cbAutoRun->currentData().toInt() > 0 ){
dOpen->setWindowTitle("Start Run Comment"); QDialog * dOpen = new QDialog(this);
dOpen->setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint); dOpen->setWindowTitle("Start Run Comment");
dOpen->setMinimumWidth(600); dOpen->setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
connect(dOpen, &QDialog::finished, dOpen, &QDialog::deleteLater); dOpen->setMinimumWidth(600);
connect(dOpen, &QDialog::finished, dOpen, &QDialog::deleteLater);
QGridLayout * vlayout = new QGridLayout(dOpen); QGridLayout * vlayout = new QGridLayout(dOpen);
QLabel *label = new QLabel("Enter Run comment for <font style=\"color : red;\">Run-" + runIDStr + "</font> : ", dOpen); QLabel *label = new QLabel("Enter Run comment for <font style=\"color : red;\">Run-" + runIDStr + "</font> : ", dOpen);
QLineEdit *lineEdit = new QLineEdit(dOpen); QLineEdit *lineEdit = new QLineEdit(dOpen);
QPushButton *button1 = new QPushButton("OK", dOpen); QPushButton *button1 = new QPushButton("OK", dOpen);
QPushButton *button2 = new QPushButton("Cancel", dOpen); QPushButton *button2 = new QPushButton("Cancel", dOpen);
vlayout->addWidget(label, 0, 0, 1, 2); vlayout->addWidget(label, 0, 0, 1, 2);
vlayout->addWidget(lineEdit, 1, 0, 1, 2); vlayout->addWidget(lineEdit, 1, 0, 1, 2);
vlayout->addWidget(button1, 2, 0); vlayout->addWidget(button1, 2, 0);
vlayout->addWidget(button2, 2, 1); vlayout->addWidget(button2, 2, 1);
connect(button1, &QPushButton::clicked, dOpen, &QDialog::accept); connect(button1, &QPushButton::clicked, dOpen, &QDialog::accept);
connect(button2, &QPushButton::clicked, dOpen, &QDialog::reject); connect(button2, &QPushButton::clicked, dOpen, &QDialog::reject);
int result = dOpen->exec(); int result = dOpen->exec();
if(result == QDialog::Accepted ){ if(result == QDialog::Accepted ){
startComment = lineEdit->text(); startComment = lineEdit->text();
if( startComment == "") startComment = "No commet was typed."; if( startComment == "") startComment = "No commet was typed.";
leRunComment->setText(startComment); leRunComment->setText(startComment);
}else{ }else{
LogMsg("Start Run aborted. "); LogMsg("Start Run aborted. ");
return; return;
} }
//}
//TODO ============ elog //TODO ============ elog
//TODO ============ update expName.sh //TODO ============ update expName.sh
@ -293,6 +309,8 @@ void MainWindow::StartACQ(){
}else{ }else{
LogMsg("=========================== Start no-save Run"); LogMsg("=========================== Start no-save Run");
} }
//============================= start digitizer
for( int i =0 ; i < nDigi; i ++){ for( int i =0 ; i < nDigi; i ++){
if( digi[i]->IsDummy () ) continue; if( digi[i]->IsDummy () ) continue;
digi[i]->Reset(); digi[i]->Reset();
@ -320,6 +338,13 @@ void MainWindow::StartACQ(){
bnStopACQ->setEnabled(true); bnStopACQ->setEnabled(true);
bnOpenScope->setEnabled(false); bnOpenScope->setEnabled(false);
chkSaveRun->setEnabled(false); chkSaveRun->setEnabled(false);
cbAutoRun->setEnabled(false);
//TODO ======= Auto Run
if( cbAutoRun->currentIndex() > 0 ){
int timeMinite = cbAutoRun->currentData().toInt();
runTimer->start(timeMinite * 60 * 1000); // unit is msec
}
} }
@ -358,6 +383,10 @@ void MainWindow::StopACQ(){
} }
} }
//TODO ======= Stop the Auto Run
runTimer->stop();
//=============== Stop digitizer
for( int i = 0; i < nDigi; i++){ for( int i = 0; i < nDigi; i++){
if( digi[i]->IsDummy () ) continue; if( digi[i]->IsDummy () ) continue;
digi[i]->StopACQ(); digi[i]->StopACQ();
@ -394,6 +423,17 @@ void MainWindow::StopACQ(){
} }
void MainWindow::AutoRun(){
if( cbAutoRun->currentData().toInt() > 0 ){
//---- stop run
}else{
//----- stop run and start a new run
}
}
//^###################################################################### open and close digitizer //^###################################################################### open and close digitizer
void MainWindow::OpenDigitizers(){ void MainWindow::OpenDigitizers(){
@ -418,6 +458,8 @@ void MainWindow::OpenDigitizers(){
chkSaveRun->setEnabled(true); chkSaveRun->setEnabled(true);
bnOpenDigitizers->setEnabled(false); bnOpenDigitizers->setEnabled(false);
bnOpenDigitizers->setStyleSheet(""); bnOpenDigitizers->setStyleSheet("");
//cbAutoRun->setEnabled(true);
cbAutoRun->setEnabled(false);
readDataThread[i] = new ReadDataThread(digi[i], this); readDataThread[i] = new ReadDataThread(digi[i], this);
connect(readDataThread[i], &ReadDataThread::sendMsg, this, &MainWindow::LogMsg); connect(readDataThread[i], &ReadDataThread::sendMsg, this, &MainWindow::LogMsg);
@ -467,13 +509,15 @@ void MainWindow::CloseDigitizers(){
bnOpenDigitizers->setEnabled(true); bnOpenDigitizers->setEnabled(true);
bnOpenDigitizers->setFocus();
bnCloseDigitizers->setEnabled(false); bnCloseDigitizers->setEnabled(false);
bnDigiSettings->setEnabled(false); bnDigiSettings->setEnabled(false);
bnStartACQ->setEnabled(false); bnStartACQ->setEnabled(false);
bnStopACQ->setEnabled(false); bnStopACQ->setEnabled(false);
bnOpenDigitizers->setFocus(); bnOpenScope->setEnabled(false);
bnOpenScalar->setEnabled(false); bnOpenScalar->setEnabled(false);
chkSaveRun->setEnabled(false); chkSaveRun->setEnabled(false);
cbAutoRun->setEnabled(false);
} }
@ -484,7 +528,7 @@ void MainWindow::OpenScope(){
if( !scope ){ if( !scope ){
scope = new Scope(digi, nDigi, readDataThread); scope = new Scope(digi, nDigi, readDataThread);
connect(scope, &Scope::CloseWindow, this, [=](){ bnStartACQ->setEnabled(true); }); connect(scope, &Scope::CloseWindow, this, [=](){ bnStartACQ->setEnabled(true); });
connect(scope, &Scope::UpdateScalar, this, &MainWindow::UpdateScalar); //connect(scope, &Scope::UpdateScalar, this, &MainWindow::UpdateScalar);
connect(scope, &Scope::SendLogMsg, this, &MainWindow::LogMsg); connect(scope, &Scope::SendLogMsg, this, &MainWindow::LogMsg);
}else{ }else{
scope->show(); scope->show();
@ -645,7 +689,7 @@ void MainWindow::UpdateScalar(){
} }
//^###################################################################### Program Settings //^###################################################################### Program Settings
void MainWindow::ProgramSettings(){ void MainWindow::ProgramSettingsPanel(){
LogMsg("Open <b>Program Settings</b>."); LogMsg("Open <b>Program Settings</b>.");
@ -772,7 +816,7 @@ void MainWindow::OpenDirectory(int id){
} }
} }
bool MainWindow::OpenProgramSettings(){ bool MainWindow::LoadProgramSettings(){
QString settingFile = QDir::current().absolutePath() + "/programSettings.txt"; QString settingFile = QDir::current().absolutePath() + "/programSettings.txt";
@ -898,6 +942,27 @@ void MainWindow::SetupInflux(){
} }
} }
void MainWindow::CheckElog(){
WriteElog("Checking elog writing", "checking", "Testing communication");
if( elogID > 0 ){
LogMsg("Ckecked Elog writing. OK.");
//TODO =========== chrome windowID
AppendElog("Check Elog append.", 10485763);
if( elogID > 0 ){
LogMsg("Checked Elog Append. OK.");
}else{
LogMsg("Checked Elog Append. FAIL. (no elog will be used.)");
}
}else{
LogMsg("Ckecked Elog writing. FAIL. (no elog will be used.)");
}
}
void MainWindow::SaveProgramSettings(){ void MainWindow::SaveProgramSettings(){
IPListStr = lIPDomain->text(); IPListStr = lIPDomain->text();
@ -932,13 +997,13 @@ void MainWindow::SaveProgramSettings(){
DecodeIPList(); DecodeIPList();
SetupInflux(); SetupInflux();
OpenExpSettings(); LoadExpSettings();
} }
//^###################################################################### Setup new exp //^###################################################################### Setup new exp
void MainWindow::SetupNewExp(){ void MainWindow::SetupNewExpPanel(){
LogMsg("Open <b>New/Change/Reload Exp</b>."); LogMsg("Open <b>New/Change/Reload Exp</b>.");
@ -1163,13 +1228,13 @@ void MainWindow::SetupNewExp(){
layout->setRowStretch(0, 1); layout->setRowStretch(0, 1);
for( int i = 1; i < rowID; i++) layout->setRowStretch(i, 2); for( int i = 1; i < rowID; i++) layout->setRowStretch(i, 2);
OpenExpSettings(); LoadExpSettings();
dialog.exec(); dialog.exec();
} }
bool MainWindow::OpenExpSettings(){ bool MainWindow::LoadExpSettings(){
//this method set the analysis setting ann symbloic link to raw data //this method set the analysis setting ann symbloic link to raw data
//ONLY load file, not check the git //ONLY load file, not check the git
@ -1219,6 +1284,8 @@ bool MainWindow::OpenExpSettings(){
bnOpenDigitizers->setStyleSheet("color:red;"); bnOpenDigitizers->setStyleSheet("color:red;");
CheckElog();
return true; return true;
} }
@ -1300,7 +1367,7 @@ void MainWindow::ChangeExperiment(const QString newExpName){
CreateRawDataFolderAndLink(newExpName); CreateRawDataFolderAndLink(newExpName);
OpenExpSettings(); LoadExpSettings();
} }
@ -1348,3 +1415,86 @@ void MainWindow::LogMsg(QString msg){
//qDebug() << msg; //qDebug() << msg;
logInfo->repaint(); logInfo->repaint();
} }
void MainWindow::WriteElog(QString htmlText, QString category, QString subject){
if( elogID < 0 ) return;
if( expName == "" ) return;
QStringList arg;
arg << "-h" << ElogIP << "-p" << "8080" << "-l" << expName << "-u" << "GeneralFSU" << "fsuphysics-888"
<< "-a" << "Author=GeneralFSU" << "-a" << "Category=" + category
<< "-a" << "Subject=" + subject
<< "-n " << "2" << htmlText ;
QProcess elogBash(this);
elogBash.start("elog", arg);
elogBash.waitForFinished();
QString output = QString::fromUtf8(elogBash.readAllStandardOutput());
int index = output.indexOf("ID=");
if( index != -1 ){
elogID = output.mid(index+3).toInt();
}else{
elogID = -1;
}
}
void MainWindow::AppendElog(QString appendHtmlText, int screenID){
if( elogID < 1 ) return;
if( expName == "" ) return;
QProcess elogBash(this);
QStringList arg;
arg << "-h" << ElogIP << "-p" << "8080" << "-l" << expName << "-u" << "GeneralFSU" << "fsuphysics-888" << "-w" << QString::number(elogID);
//retrevie the elog
elogBash.start("elog", arg);
elogBash.waitForFinished();
QString output = QString::fromUtf8(elogBash.readAllStandardOutput());
//qDebug() << output;
QString separator = "========================================";
int index = output.indexOf(separator);
if( index != -1){
QString originalHtml = output.mid(index + separator.length());
arg.clear();
arg << "-h" << ElogIP << "-p" << "8080" << "-l" << expName << "-u" << "GeneralFSU" << "fsuphysics-888" << "-e" << QString::number(elogID)
<< "-n" << "2" << originalHtml + "<br>" + appendHtmlText;
if( screenID >= 0) {
//TODO =========== chrome windowID
QScreen * screen = QGuiApplication::primaryScreen();
if( screen){
QPixmap screenshot = screen->grabWindow(screenID);
screenshot.save("screenshot.png");
arg << "-f" << "screenshot.png";
}
}
elogBash.start("elog", arg);
elogBash.waitForFinished();
output = QString::fromUtf8(elogBash.readAllStandardOutput());
index = output.indexOf("ID=");
if( index != -1 ){
elogID = output.mid(index+3).toInt();
}else{
elogID = -1;
}
}else{
elogID = -1;
}
}

View File

@ -11,6 +11,7 @@
#include <QPushButton> #include <QPushButton>
#include <QComboBox> #include <QComboBox>
#include <QLabel> #include <QLabel>
#include <QTimer>
#include <QChart> #include <QChart>
#include <QLineSeries> #include <QLineSeries>
@ -18,6 +19,7 @@
#include <vector> #include <vector>
#include <time.h> // time in nano-sec #include <time.h> // time in nano-sec
#include "ClassDigitizer2Gen.h" #include "ClassDigitizer2Gen.h"
#include "influxdb.h" #include "influxdb.h"
@ -43,20 +45,23 @@ private slots:
void OpenScope(); void OpenScope();
void OpenDigitizersSettings(); void OpenDigitizersSettings();
void AutoRun();
void OpenScaler(); void OpenScaler();
void SetUpScalar(); void SetUpScalar();
void DeleteTriggerLineEdit(); void DeleteTriggerLineEdit();
void UpdateScalar(); void UpdateScalar();
void ProgramSettings(); void ProgramSettingsPanel();
bool OpenProgramSettings(); bool LoadProgramSettings();
void SaveProgramSettings(); void SaveProgramSettings();
void DecodeIPList(); void DecodeIPList();
void SetupInflux(); void SetupInflux();
void CheckElog();
void OpenDirectory(int id); void OpenDirectory(int id);
void SetupNewExp(); void SetupNewExpPanel();
bool OpenExpSettings(); bool LoadExpSettings();
void CreateNewExperiment(const QString newExpName); void CreateNewExperiment(const QString newExpName);
void ChangeExperiment(const QString newExpName); void ChangeExperiment(const QString newExpName);
void CreateRawDataFolderAndLink(const QString newExpName); void CreateRawDataFolderAndLink(const QString newExpName);
@ -67,6 +72,8 @@ private slots:
event->accept(); event->accept();
} }
void WriteElog(QString htmlText, QString category = "", QString subject = "");
void AppendElog(QString appendHtmlText, int screenID = -1);
signals : signals :
@ -146,7 +153,11 @@ private:
QString rawDataFolder; QString rawDataFolder;
unsigned int runID; unsigned int runID;
QString runIDStr; QString runIDStr;
unsigned int elogID; int elogID; // 0 = ready, -1 = disable, >1 = elogID
QTimer * runTimer;
unsigned int autoRunStartRunID;
}; };

8
makeTest.sh Normal file → Executable file
View File

@ -22,7 +22,11 @@ OBJS="ClassDigitizer2Gen.o influxdb.o"
echo "------- influxdb.o"
${CC} ${COPTS} -c influxdb.cpp ${CURLLIBS} ${CC} ${COPTS} -c influxdb.cpp ${CURLLIBS}
echo "------- ClassDigitizer2Gen.o"
${CC} ${COPTS} -c ClassDigitizer2Gen.cpp ${CAENLIBS} ${CC} ${COPTS} -c ClassDigitizer2Gen.cpp ${CAENLIBS}
${CC} ${COPTS} ${OBJS} -o test test.cpp ${CAENLIBS} ${CURLLIBS} echo "------- test"
${CC} ${COPTS} ${OBJS} -o test test.cpp ${CAENLIBS} ${CURLLIBS}
echo "------- windowID"
${CC} ${COPTS} -o windowID windowID.cpp -lX11 -lpng

View File

@ -63,6 +63,8 @@ public:
waitTime = 2; waitTime = 2;
stop = false; stop = false;
} }
unsigned int GetWaitTimeSec() const {return waitTime;}
void SetWaitTimeSec(unsigned sec) {waitTime = sec;}
void Stop() {this->stop = true;} void Stop() {this->stop = true;}
void run(){ void run(){
unsigned int count = 0; unsigned int count = 0;

View File

@ -327,7 +327,11 @@ Scope::Scope(Digitizer2Gen **digi, unsigned int nDigi, ReadDataThread ** readDat
//------------- Ketbinding //------------- Ketbinding
rowID ++; rowID ++;
QLabel * lbhints = new QLabel("Type 'r' to restore view.", this); QLabel * lbhints = new QLabel("Type 'r' to restore view.", this);
layout->addWidget(lbhints, rowID, 0, 1, 4); layout->addWidget(lbhints, rowID, 0, 1, 3);
QLabel * lbinfo = new QLabel("Trace update every " + QString::number(updateTraceThread->GetWaitTimeSec()) + " sec.", this);
lbinfo->setAlignment(Qt::AlignRight);
layout->addWidget(lbinfo, rowID, 5);
//------------ close button //------------ close button
rowID ++; rowID ++;

94
windowID.cpp Normal file
View File

@ -0,0 +1,94 @@
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <png.h>
#include <fstream>
#include <cstring>
#include <vector>
#include <iostream>
void saveScreenshot(Display* display, const Window window, const char* filename){
XWindowAttributes attrs;
XGetWindowAttributes(display, window, &attrs);
printf("(x,y) :(%d, %d), (w,h) : (%d, %d) \n", attrs.x, attrs.y, attrs.width, attrs.height);
int window_width = attrs.width;
int window_height = attrs.height;
XImage *image = XGetImage(display, window, 0, 0, window_width, window_height, AllPlanes, ZPixmap);
png_bytep *row_pointers = new png_bytep[window_height];
for (int i = 0; i < window_height; i++) {
row_pointers[i] = (png_bytep)(image->data + i * image->bytes_per_line);
}
FILE *png_file = fopen(filename, "w");
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
png_infop info_ptr = png_create_info_struct(png_ptr);
png_init_io(png_ptr, png_file);
png_set_IHDR(png_ptr, info_ptr, window_width, window_height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_write_info(png_ptr, info_ptr);
png_write_image(png_ptr, row_pointers);
png_write_end(png_ptr, NULL);
png_destroy_write_struct(&png_ptr, &info_ptr);
fclose(png_file);
XFree(image->data);
}
int main(int argc, char* argv[]){
Window screenID;
if( argc > 1){
screenID = atoi(argv[1]);
}
// Connect to the X server
Display *display = XOpenDisplay(nullptr);
//============== show all windows ID
Window root = DefaultRootWindow(display);
Window parent;
Window *children;
unsigned int numChildren;
Status status = XQueryTree(display, root, &root, &parent, &children, &numChildren);
if (!status) {
std::cerr << "Failed to query window tree\n";
return 1;
}
for (unsigned int i = 0; i < numChildren; i++) {
XTextProperty windowName;
status = XGetWMName(display, children[i], &windowName);
if( i == 0 ) {
printf("%12s | %12s \n", "Window ID", "Name");
printf("--------------+--------------------------------\n");
}
if (status) {
char **list;
int count;
status = XmbTextPropertyToTextList(display, &windowName, &list, &count);
if (status >= Success && count > 0 && *list) {
printf("%12ld | %s \n", children[i], *list);
//std::cout << "Window ID: " << children[i] << ", Window Name: " << *list << "\n";
XFreeStringList(list);
}
XFree(windowName.value);
}
}
XFree(children);
//================ end of show windows ID
if( argc >1 ){
saveScreenshot(display, screenID, "screenshot.png");
printf("captured screenshot of windowID(%ld) as screenshot.png\n", screenID);
}
// Close the display connection
XCloseDisplay(display);
return 0;
}