Commit initial

This commit is contained in:
Valentin Verdier 2020-07-13 00:37:45 +02:00
commit 69b2cb0def
14 changed files with 470 additions and 0 deletions

49
src/Exception.cpp Normal file
View File

@ -0,0 +1,49 @@
#include <exception>
#include <string>
#include <sstream>
#include "Exception.hpp"
Kronos::Exception::Exception::Exception() : m_cause(nullptr) {
initTrace();
}
Kronos::Exception::Exception::Exception(const std::string& message) : m_cause(nullptr), m_message(message) {
initTrace();
}
Kronos::Exception::Exception::Exception(const std::string& message, const std::exception& cause) : m_cause(&cause), m_message(message) {
initTrace();
}
Kronos::Exception::Exception::Exception(const std::exception& cause) : m_cause(&cause) {
initTrace();
}
void Kronos::Exception::Exception::initTrace() {
std::stringstream ss;
const std::string& msg = getMessage();
ss << typeid(*this).name();
if(!msg.empty()) {
ss << " : " << msg;
}
if(m_cause != nullptr) {
ss << "\n -> " << m_cause->what();
}
m_trace = ss.str();
}
const char* Kronos::Exception::Exception::what() const noexcept {
return m_trace.c_str();
}
const std::exception* Kronos::Exception::Exception::getCause() const {
return m_cause;
}
const std::string& Kronos::Exception::Exception::getMessage() const {
return m_message;
}

31
src/Exception.hpp Normal file
View File

@ -0,0 +1,31 @@
#ifndef KRONOS_EXCEPTION_HEADER
#define KRONOS_EXCEPTION_HEADER
#include <exception>
#include <string>
namespace Kronos {
namespace Exception {
class Exception : public std::exception {
private:
const std::exception* m_cause;
const std::string m_message;
std::string m_trace;
void initTrace();
public:
Exception();
Exception(const std::string& message);
Exception(const std::exception& cause);
Exception(const std::string& message, const std::exception& cause);
const char* what() const noexcept;
const std::exception* getCause() const;
virtual const std::string& getMessage() const;
};
}
}
#endif

15
src/IOException.hpp Normal file
View File

@ -0,0 +1,15 @@
#ifndef KRONOS_IOEXCEPTION_HEADER
#define KRONOS_IOEXCEPTION_HEADER
#include "Exception.hpp"
namespace Kronos {
namespace Exception {
class IOException : public Exception {
using Exception::Exception;
};
}
}
#endif

76
src/Logger.cpp Normal file
View File

@ -0,0 +1,76 @@
#include <iostream>
#include <fstream>
#include <cassert>
#include <ctime>
#include <sstream>
#include <string>
#include "IOException.hpp"
#include "Logger.hpp"
Kronos::Logger* Kronos::Logger::s_instance = nullptr;
void Kronos::Logger::Log(const std::string& msg) {
Kronos::Logger::Log(Kronos::Logger::Level::INFO, msg);
}
void Kronos::Logger::Log(Kronos::Logger::Level level, const std::string& msg) {
assert(Kronos::Logger::s_instance != nullptr);
Kronos::Logger::s_instance->log(level, msg);
}
Kronos::Logger::Logger(Kronos::Logger::Level level, const char* filename, bool console)
: m_level(level), m_console(console) {
assert(Kronos::Logger::s_instance == nullptr);
if(filename != nullptr) {
m_logFile.open(filename, std::ofstream::app);
if(!m_logFile.is_open()) {
throw Kronos::Exception::IOException("Unable to open log file <" + std::string(filename) + ">");
}
}
Kronos::Logger::s_instance = this;
}
Kronos::Logger::~Logger() {
if(m_logFile.is_open()) {
m_logFile.close();
}
Kronos::Logger::s_instance = nullptr;
}
void Kronos::Logger::setLevel(Kronos::Logger::Level level) {
m_level = level;
}
void Kronos::Logger::log(Kronos::Logger::Level level, const std::string& msg) {
if(level <= m_level) {
time_t curTime = time(nullptr);
std::stringstream ss;
char dtStr[20];
strftime(dtStr, 20, "%Y-%m-%d %H:%M:%S", localtime(&curTime));
const char* lvlName = nullptr;
if(level == Kronos::Logger::Level::ERROR) {
lvlName = "ERROR";
} else if(level == Kronos::Logger::Level::WARN) {
lvlName = "WARN";
} else if(level == Kronos::Logger::Level::DEBUG) {
lvlName = "DEBUG";
} else {
lvlName = "INFO";
}
ss << "[" << dtStr << "]" << "[" << lvlName << "] : " << msg;
if(m_logFile.is_open()) {
m_logFile << ss.str() << std::endl;
}
if(m_console) {
std::cout << ss.str() << std::endl;
}
}
}

35
src/Logger.hpp Normal file
View File

@ -0,0 +1,35 @@
#ifndef KRONOS_LOGGER_HEADER
#define KRONOS_LOGGER_HEADER
#include <fstream>
#include <string>
namespace Kronos {
class Logger final {
public:
enum Level {ERROR = 0, WARN = 1, INFO = 2, DEBUG = 3};
static void Log(const std::string& msg);
static void Log(Level level, const std::string& msg);
Logger(Level level = Level::INFO, const char* filename = nullptr, bool console = true);
Logger(const Logger& logger) = delete;
~Logger();
Logger& operator=(const Logger& logger) = delete;
void setLevel(Level level);
private:
void log(Level level, const std::string& msg);
static Logger* s_instance;
Level m_level;
std::ofstream m_logFile;
bool m_console;
};
}
#endif

33
src/Makefile Normal file
View File

@ -0,0 +1,33 @@
.PHONY: clean
CXX=g++
CXXFLAGS_DEBUG:=$(CXXFLAGS) -Wall -std=c++17 -g
CXXFLAGS:=$(CXXFLAGS) -Wall -std=c++17 -O2 -s
LDFLAGS:=$(LDFLAGS)
INC_CXXFLAGS=
LIBS=-lX11
TARGETS=kronos
TARGETS_DEBUG=kronos_dbg
SRC=main.cpp Exception.cpp Logger.cpp XDisplayConnection.cpp XWindow.cpp
OBJ=$(SRC:.cpp=.o)
OBJ_DEBUG=$(SRC:.cpp=.odbg)
all: $(TARGETS)
debug: $(TARGETS_DEBUG)
kronos: $(OBJ)
$(CXX) $(LDFLAGS) $(LIBS) $^ -o $@
kronos_dbg: $(OBJ_DEBUG)
$(CXX) $(LDFLAGS) $(LIBS) $^ -o $@
%.o: %.cpp
$(CXX) $(CXXFLAGS) $(INC_CXXFLAGS) -c $^ -o $@
%.odbg: %.cpp
$(CXX) $(CXXFLAGS_DEBUG) $(INC_CXXFLAGS) -c $^ -o $@
clean:
rm -f $(TARGETS) $(TARGETS_DEBUG) $(OBJ) $(OBJ_DEBUG)

13
src/WindowRecorder.hpp Normal file
View File

@ -0,0 +1,13 @@
#ifndef WINDOW_RECORDER_HEADER
#define WINDOW_RECORDER_HEADER
namespace Kronos {
class WindowRecorder {
public:
virtual ~WindowRecorder() = 0;
virtual prepare
};
}
#endif

View File

@ -0,0 +1,45 @@
#include <vector>
#include <string>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include "Logger.hpp"
#include "XWindow.hpp"
#include "XDisplayInitException.hpp"
#include "XDisplayConnection.hpp"
Kronos::XDisplayConnection::XDisplayConnection(const char* name) {
m_display = XOpenDisplay(name);
if(m_display == nullptr) {
throw Kronos::Exception::XDisplayInitException("Unable to open X display");
}
}
Kronos::XDisplayConnection::~XDisplayConnection() {
XCloseDisplay(m_display);
}
Display* Kronos::XDisplayConnection::getDisplay() {
return m_display;
}
std::vector<Kronos::XWindow> Kronos::XDisplayConnection::getWindows() {
std::vector<XWindow> windows;
Atom propWin = XInternAtom(m_display, "_NET_CLIENT_LIST", False);
Atom type;
int form;
unsigned long remain, len;
unsigned char* prop = nullptr;
if(XGetWindowProperty(m_display, XDefaultRootWindow(m_display), propWin, 0, 1024, False, XA_WINDOW, &type, &form, &len, &remain, &prop) == Success) {
Window* wins = (Window*) prop;
for(unsigned long i = 0; i < len; i++) {
windows.push_back(Kronos::XWindow(*this, wins[i]));
}
XFree(prop);
} else {
Kronos::Logger::Log(Kronos::Logger::Level::ERROR, "Unable to get windows list from XGetWindowProperty");
}
return windows;
}

View File

@ -0,0 +1,26 @@
#ifndef KRONOS_XDISPLAY_CONNECTION_HEADER
#define KRONOS_XDISPLAY_CONNECTION_HEADER
#include <vector>
#include <X11/Xlib.h>
#include "XWindow.hpp"
namespace Kronos {
class XDisplayConnection {
public:
XDisplayConnection(const char* name = nullptr);
XDisplayConnection(const XDisplayConnection& conn) = delete;
~XDisplayConnection();
XDisplayConnection& operator=(const XDisplayConnection& conn) = delete;
Display* getDisplay();
std::vector<XWindow> getWindows();
private:
Display* m_display;
};
}
#endif

View File

@ -0,0 +1,15 @@
#ifndef KRONOS_XDISPLAYINITEXCEPTION_HEADER
#define KRONOS_XDISPLAYINITEXCEPTION_HEADER
#include "Exception.hpp"
namespace Kronos {
namespace Exception {
class XDisplayInitException : public Exception {
using Exception::Exception;
};
}
}
#endif

63
src/XWindow.cpp Normal file
View File

@ -0,0 +1,63 @@
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <string>
#include "XDisplayConnection.hpp"
#include "XWindowInitException.hpp"
#include "XWindow.hpp"
Kronos::XWindow::XWindow(Kronos::XDisplayConnection& conn, Window window)
: m_conn(conn), m_window(window) {
Atom propName = XInternAtom(m_conn.getDisplay(), "WM_NAME", False);
Atom type;
int form;
unsigned long remain, len;
unsigned char* prop = nullptr;
if(XGetWindowProperty(m_conn.getDisplay(), m_window, propName, 0, 1024, False, AnyPropertyType, &type, &form, &len, &remain, &prop) == Success) {
m_name = (const char*) prop;
XFree(prop);
}
XWindowAttributes attr;
if(!XGetWindowAttributes(m_conn.getDisplay(), m_window, &attr)) {
throw Kronos::Exception::XWindowInitException();
}
m_width = attr.width;
m_height = attr.height;
XSelectInput(m_conn.getDisplay(), m_window, StructureNotifyMask);
XSync(m_conn.getDisplay(), 0);
}
Kronos::XWindow::~XWindow() {
XSelectInput(m_conn.getDisplay(), m_window, 0);
}
void Kronos::XWindow::processEvents() {
/*
* IT DOES'T WORK !!
*/
while(XEventsQueued(m_conn.getDisplay(), QueuedAfterReading) > 0) {
XEvent event;
XNextEvent(m_conn.getDisplay(), &event);
if(event.type == ConfigureNotify) {
XConfigureEvent conf = event.xconfigure;
m_width = conf.width;
m_height = conf.height;
}
}
}
std::string Kronos::XWindow::getName() const {
return m_name;
}
int Kronos::XWindow::getWidth() const {
return m_width;
}
int Kronos::XWindow::getHeight() const {
return m_height;
}

31
src/XWindow.hpp Normal file
View File

@ -0,0 +1,31 @@
#ifndef KRONOS_XWINDOW_HEADER
#define KRONOS_XWINDOW_HEADER
#include <X11/Xlib.h>
#include <string>
//#include "XDisplayConnection.hpp"
namespace Kronos {
class XDisplayConnection;
class XWindow {
public:
XWindow(XDisplayConnection& conn, Window window);
~XWindow();
void processEvents();
std::string getName() const;
int getWidth() const;
int getHeight() const;
private:
XDisplayConnection& m_conn;
Window m_window;
std::string m_name;
int m_width;
int m_height;
};
}
#endif

View File

@ -0,0 +1,15 @@
#ifndef KRONOS_XWINDOWINITEXCEPTION_HEADER
#define KRONOS_XWINDOWINITEXCEPTION_HEADER
#include "Exception.hpp"
namespace Kronos {
namespace Exception {
class XWindowInitException : public Exception {
using Exception::Exception;
};
}
}
#endif

23
src/main.cpp Normal file
View File

@ -0,0 +1,23 @@
#include <iostream>
#include <vector>
#include "Exception.hpp"
#include "Logger.hpp"
#include "XDisplayConnection.hpp"
#include "XWindow.hpp"
int main(int argc, char** argv) {
Kronos::Logger logger(Kronos::Logger::Level::INFO, "kronos.log");
Kronos::Logger::Log("=============== Kronos v0.1 ===============");
Kronos::XDisplayConnection display;
std::vector<Kronos::XWindow> windows = display.getWindows();
for(Kronos::XWindow& w : windows) {
w.processEvents();
std::cout << "=> " << w.getName() << std::endl;
std::cout << " - " << w.getWidth() << "x" << w.getHeight() << std::endl;
}
return 0;
}