roundabout,
created on Monday, 30 June 2025, 14:25:55 (1751293555),
received on Monday, 30 June 2025, 14:25:58 (1751293558)
Author identity: vlad <vlad.muntoiu@gmail.com>
68cbca25dceaad0f844361b8dd1f9c882e71d377
gpanthera.cc
@@ -966,6 +966,7 @@ namespace gPanthera {
this->get_stack()->set_visible_child(*this->get_prev_sibling());
}
this->redock(nullptr);
content_manager->signal_page_closed.emit(this);
}
}
@@ -1008,7 +1009,7 @@ namespace gPanthera {
void ContentPage::redock(ContentStack *stack) {
if(stack == nullptr) {
content_manager->signal_page_moving.emit(this);
content_manager->signal_page_closing.emit(this);
if(this->stack) {
this->stack->remove(*this);
if(dynamic_cast<ContentNotebook*>(this->stack->get_parent()) && !this->stack->get_first_child()) {
@@ -1111,8 +1112,10 @@ namespace gPanthera {
this->last_operated_page->signal_control_status_changed.emit(false);
}
this->last_operated_page = page;
page->signal_control_status_changed.emit(true);
this->signal_page_operated.emit(page);
if(page) {
page->signal_control_status_changed.emit(true);
this->signal_page_operated.emit(page);
}
}
DockWindow *DockablePane::get_window() const {
gpanthera.hh
@@ -127,7 +127,7 @@ namespace gPanthera {
public:
ContentPage *get_last_operated_page() const;
void set_last_operated_page(ContentPage *page);
sigc::signal<void(ContentPage*)> signal_page_operated, signal_page_moving, signal_page_moved;
sigc::signal<void(ContentPage*)> signal_page_operated, signal_page_moving, signal_page_moved, signal_page_closing, signal_page_closed;
std::vector<ContentStack*> stacks;
ContentManager();
panthera-www.cc
@@ -113,6 +113,20 @@ public:
}
};
std::vector<WebKitWebView*> collect_webviews(Gtk::Widget const &root) {
std::vector<WebKitWebView*> result;
std::function<void(const Gtk::Widget&)> recurse = [&](const Gtk::Widget &widget) {
gpointer gobj = G_OBJECT(widget.gobj());
if(WEBKIT_IS_WEB_VIEW(gobj)) {
result.push_back(WEBKIT_WEB_VIEW(gobj));
} else for(auto *child = widget.get_first_child(); child; child = child->get_next_sibling()) {
recurse(*child);
}
};
recurse(root);
return result;
}
class HistoryViewer : public gPanthera::DockablePane {
protected:
std::shared_ptr<HistoryManager> history_manager;
@@ -290,6 +304,7 @@ private:
static void on_back_pressed(GtkGestureClick* gesture, int n_press, double x, double y, gpointer user_data);
static void on_forward_pressed(GtkGestureClick* gesture, int n_press, double x, double y, gpointer user_data);
static gboolean on_decide_policy(WebKitWebView* source, WebKitPolicyDecision* decision, WebKitPolicyDecisionType type, gpointer user_data);
static void close_callback(WebKitWebView *source, gpointer user_data);
protected:
void on_startup() override;
@@ -392,10 +407,18 @@ public:
auto window = new gPanthera::ContentWindow(new_notebook);
widget->redock(new_stack);
window->present();
new_stack->signal_leave_empty.connect([window]() {
window->close();
delete window;
});
window->signal_close_request().connect([window]() {
auto webviews = collect_webviews(*window);
for(auto view : webviews) {
webkit_web_view_try_close(view);
}
webviews = collect_webviews(*window);
if(webviews.empty()) {
// All documents have been closed safely, the window can be closed
return false;
}
return true;
}, false);
controlled_page = nullptr;
controlled_stack = nullptr;
disable_controls();
@@ -445,6 +468,9 @@ public:
go_button->signal_clicked().connect(load_url_callback);
url_bar->signal_activate().connect(load_url_callback);
panthera->content_manager->signal_page_operated.connect([this, panthera](gPanthera::ContentPage *page) {
if(!page) {
return;
}
if(!page->get_child()) {
return;
}
@@ -613,6 +639,19 @@ public:
enable_controls();
}
});
signal_close_request().connect([this]() {
auto webviews = collect_webviews(*this);
for(auto view : webviews) {
webkit_web_view_try_close(view);
}
webviews = collect_webviews(*this);
if(webviews.empty()) {
// All documents have been closed safely, the window can be closed
return false;
}
return true;
}, false);
}
~PantheraWindow() override {
moving_connection.disconnect();
@@ -725,6 +764,26 @@ gboolean PantheraWww::on_decide_policy(WebKitWebView *source, WebKitPolicyDecisi
return false;
}
void PantheraWww::close_callback(WebKitWebView *source, gpointer user_data) {
if(auto self = static_cast<PantheraWww*>(user_data)) {
auto parent = gtk_widget_get_parent(gtk_widget_get_parent(GTK_WIDGET(source)));
if(auto page = dynamic_cast<gPanthera::ContentPage*>(Glib::wrap(parent))) {
if(page->get_next_sibling()) {
page->content_manager->set_last_operated_page(static_cast<gPanthera::ContentPage*>(page->get_next_sibling()));
page->get_stack()->set_visible_child(*page->get_next_sibling());
} else if(page->get_prev_sibling()) {
page->content_manager->set_last_operated_page(static_cast<gPanthera::ContentPage*>(page->get_prev_sibling()));
page->get_stack()->set_visible_child(*page->get_prev_sibling());
}
webkit_web_view_terminate_web_process(source);
if(page->content_manager->get_last_operated_page() == page) {
page->content_manager->set_last_operated_page(nullptr);
}
page->redock(nullptr);
}
}
}
void PantheraWww::on_new_tab(gPanthera::ContentStack *stack, const Glib::ustring &url, bool focus, bool new_window) {
if(!stack) {
// Find the current area
@@ -747,6 +806,11 @@ void PantheraWww::on_new_tab(gPanthera::ContentStack *stack, const Glib::ustring
page_tab->append(*Gtk::make_managed<Gtk::Label>(_("Untitled")));
page_tab->set_spacing(4);
auto page = Gtk::make_managed<gPanthera::ContentPage>(content_manager, stack, page_content, page_tab);
page->signal_close.connect([webview]() {
webkit_web_view_try_close(WEBKIT_WEB_VIEW(webview));
return true;
});
g_signal_connect(webview, "close", G_CALLBACK(close_callback), this);
g_signal_connect(webview, "notify", G_CALLBACK(notify_callback), this);
g_signal_connect(webview, "load-changed", G_CALLBACK(load_change_callback), this);
g_signal_connect(webview, "decide-policy", G_CALLBACK(on_decide_policy), this);
@@ -801,6 +865,9 @@ void PantheraWww::on_startup() {
// Set window titles on tab switch
content_manager->signal_page_operated.connect([this](gPanthera::ContentPage *page) {
if(!page) {
return;
}
if(auto window = dynamic_cast<Gtk::Window*>(page->get_root())) {
if(webkit_web_view_get_title(WEBKIT_WEB_VIEW(page->get_child()->get_first_child()->gobj()))) {
window->set_title(webkit_web_view_get_title(WEBKIT_WEB_VIEW(page->get_child()->get_first_child()->gobj())));