#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "webengine.hpp" bool is_valid_url(const std::string & url); void open_url(const std::string & url); void search(); void page_scroll(int scroll); void goto_end(bool end); void get_window_id(); void history_move(bool back); void reload(); uint32_t parent_id = 0; #include "config.hpp" bool is_valid_url(const std::string & url) { std::regex r(".*://.*\\..*"); std::smatch m; return std::regex_match(url, m, r); } QWebEngineView * web; QMainWindow * view; Display * dpy; std::string read_from_dmenu() { std::string output; std::string cmd = std::string("printf '' | dmenu -p 'open: ' ") + dmenu_args + " -w "; cmd += std::to_string(view->winId()); FILE * f = popen(cmd.c_str(), "r"); char string[8092] = {0}; fgets(string, 8092, f); fclose(f); if (string[0] != 0) { output = string; output.pop_back(); } return output; } void open_url(const std::string & url) { web->load(QString::fromStdString(url)); } void search() { auto url = read_from_dmenu(); if (url.empty()) return; if (is_valid_url(url)) { open_url(url); return; } if (is_valid_url("https://" + url)) { open_url("https://" + url); return; } open_url(search_engine + url); } void page_scroll(int scroll) { std::string js = "window.scrollBy({ top: " + std::to_string(scroll) + ", behavior: 'smooth' });"; web->page()->runJavaScript(QString::fromStdString(js)); } void goto_end(bool end) { std::string js; if (end) js = "window.scroll({ top: document.body.scrollHeight, behavior: 'smooth' })"; else js = "window.scroll({ top: 0, behavior: 'smooth' })"; web->page()->runJavaScript(QString::fromStdString(js)); } void history_move(bool back) { if (back) web->back(); else web->forward(); } void reload() { web->reload(); } void help(char *arg0) { std::cout << arg0 << '\n'; std::cout << "-e [xid] - embed in other X window\n"; } int main(int argc, char **argv) { QApplication app(argc, argv); QWebEngineProfile profile; WebEnginePage page(&profile); QProgressBar progressbar; QLabel url_label; QWidget *main = new QWidget; QVBoxLayout layout(main); view = new QMainWindow(); web = new QWebEngineView(); web->setPage(&page); web->load(QUrl(getenv("WWW_HOME"))); page.setBackgroundColor(QColor(40, 40, 40)); progressbar.setMaximum(100); progressbar.setMinimum(0); progressbar.setTextVisible(false); progressbar.setMaximumHeight(10); progressbar.setStyleSheet("QProgressBar::chunk { background: #b16286; border-radius: 0px }"); url_label.setMaximumHeight(30); url_label.setMargin(5); url_label.setStyleSheet("QLabel { background: #1d2021; color: #ebdbb2 }"); if (argc == 3 && argv[1] == std::string("-e")) { dpy = XOpenDisplay(NULL); parent_id = std::stoi(argv[2]); XReparentWindow(dpy, view->winId(), parent_id, 0, 0); XFlush(dpy); } else if (argc != 1) { help(argv[0]); } layout.setContentsMargins(0, 0, 0, 0); layout.setSpacing(0); layout.addWidget(web); layout.addWidget(&progressbar); layout.addWidget(&url_label); view->setCentralWidget(main); view->show(); web->connect(web, &QWebEngineView::titleChanged, [&](const QString & title) { view->setWindowTitle(title); }); if (parent_id != 0) { web->setContextMenuPolicy(Qt::CustomContextMenu); web->connect(web, &QWebEngineView::customContextMenuRequested, [&](){ auto menu = web->page()->createStandardContextMenu(); menu->popup(QCursor::pos()); return menu; }); } web->connect(web, &QWebEngineView::loadProgress, [&](int progress) { progressbar.show(); progressbar.setValue(progress); }); web->connect(web, &QWebEngineView::loadFinished, [&](bool ok) { progressbar.hide(); }); web->connect(web, &QWebEngineView::urlChanged, [&](const QUrl & url) { url_label.setText(url.toString()); }); register_shortcuts(view); return app.exec(); }