// SPDX-License-Identifier: GPL-2.0-or-later /** * @file * A dockable dialog implementation. */ /* Author: * Gustav Broberg * * Copyright (C) 2007 Authors * * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ #include "dock-behavior.h" #include "inkscape.h" #include "desktop.h" #include "ui/widget/dock.h" #include "verbs.h" #include "dialog.h" #include "ui/dialog-events.h" namespace Inkscape { namespace UI { namespace Dialog { namespace Behavior { DockBehavior::DockBehavior(Dialog &dialog) : Behavior(dialog), _dock_item(*SP_ACTIVE_DESKTOP->getDock(), Inkscape::Verb::get(dialog._verb_num)->get_id(), dialog._title.c_str(), (Inkscape::Verb::get(dialog._verb_num)->get_image() ? Inkscape::Verb::get(dialog._verb_num)->get_image() : ""), static_cast( Inkscape::Preferences::get()->getInt(_dialog._prefs_path + "/state", UI::Widget::DockItem::DOCKED_STATE)), static_cast( Inkscape::Preferences::get()->getInt(_dialog._prefs_path + "/placement", GDL_DOCK_TOP))) { // Connect signals _signal_hide_connection = signal_hide().connect(sigc::mem_fun(*this, &Inkscape::UI::Dialog::Behavior::DockBehavior::_onHide)); signal_show().connect(sigc::mem_fun(*this, &Inkscape::UI::Dialog::Behavior::DockBehavior::_onShow)); _dock_item.signal_state_changed().connect(sigc::mem_fun(*this, &Inkscape::UI::Dialog::Behavior::DockBehavior::_onStateChanged)); if (_dock_item.getState() == Widget::DockItem::FLOATING_STATE) { if (Gtk::Window *floating_win = _dock_item.getWindow()) { sp_transientize(GTK_WIDGET(floating_win->gobj())); } } } DockBehavior::~DockBehavior() = default; Behavior * DockBehavior::create(Dialog &dialog) { return new DockBehavior(dialog); } DockBehavior::operator Gtk::Widget &() { return _dock_item.getWidget(); } GtkWidget * DockBehavior::gobj() { return _dock_item.gobj(); } Gtk::VBox * DockBehavior::get_vbox() { return _dock_item.get_vbox(); } void DockBehavior::present() { bool was_attached = _dock_item.isAttached(); _dock_item.present(); if (!was_attached) _dialog.read_geometry(); } void DockBehavior::hide() { _signal_hide_connection.block(); _dock_item.hide(); _signal_hide_connection.unblock(); } void DockBehavior::show() { _dock_item.show(); } void DockBehavior::show_all_children() { get_vbox()->show_all_children(); } void DockBehavior::get_position(int &x, int &y) { _dock_item.get_position(x, y); } void DockBehavior::get_size(int &width, int &height) { _dock_item.get_size(width, height); } void DockBehavior::resize(int width, int height) { _dock_item.resize(width, height); } void DockBehavior::move(int x, int y) { _dock_item.move(x, y); } void DockBehavior::set_position(Gtk::WindowPosition position) { _dock_item.set_position(position); } void DockBehavior::set_size_request(int width, int height) { _dock_item.set_size_request(width, height); } void DockBehavior::size_request(Gtk::Requisition &requisition) { _dock_item.size_request(requisition); } void DockBehavior::set_title(Glib::ustring title) { _dock_item.set_title(title); } void DockBehavior::set_sensitive(bool sensitive) { // TODO check this. Seems to be bad that we ignore the parameter get_vbox()->set_sensitive(); } void DockBehavior::_onHide() { _dialog.save_geometry(); _dialog._user_hidden = true; } void DockBehavior::_onShow() { _dialog._user_hidden = false; } void DockBehavior::_onStateChanged(Widget::DockItem::State /*prev_state*/, Widget::DockItem::State new_state) { // TODO probably need to avoid window calls unless the state is different. Check. if (new_state == Widget::DockItem::FLOATING_STATE) { if (Gtk::Window *floating_win = _dock_item.getWindow()) sp_transientize(GTK_WIDGET(floating_win->gobj())); } } void DockBehavior::onHideF12() { _dialog.save_geometry(); hide(); } void DockBehavior::onShowF12() { present(); } void DockBehavior::onShutdown() { int visible = _dock_item.isIconified() || !_dialog._user_hidden; int status = (_dock_item.getState() == Inkscape::UI::Widget::DockItem::UNATTACHED) ? _dock_item.getPrevState() : _dock_item.getState(); _dialog.save_status( visible, status, _dock_item.getPlacement() ); } void DockBehavior::onDesktopActivated(SPDesktop *desktop) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); gint transient_policy = prefs->getIntLimited( "/options/transientpolicy/value", 1, 0, 2); #ifdef _WIN32 // Win32 special code to enable transient dialogs transient_policy = 2; #endif if (!transient_policy) return; Gtk::Window *floating_win = _dock_item.getWindow(); if (floating_win) { if (_dialog.retransientize_suppress) { /* if retransientizing of this dialog is still forbidden after * previous call warning turned off because it was confusingly fired * when loading many files from command line */ // g_warning("Retranzientize aborted! You're switching windows too fast!"); return; } if (GtkWindow *dialog_win = floating_win->gobj()) { _dialog.retransientize_suppress = true; // disallow other attempts to retranzientize this dialog desktop->setWindowTransient (dialog_win); /* * This enables "aggressive" transientization, * i.e. dialogs always emerging on top when you switch documents. Note * however that this breaks "click to raise" policy of a window * manager because the switched-to document will be raised at once * (so that its transients also could raise) */ if (transient_policy == 2 && ! _dialog._hiddenF12 && !_dialog._user_hidden) { // without this, a transient window not always emerges on top gtk_window_present (dialog_win); } } // we're done, allow next retransientizing not sooner than after 120 msec g_timeout_add (120, (GSourceFunc) sp_retransientize_again, (gpointer) &_dialog); } } /* Signal wrappers */ Glib::SignalProxy0 DockBehavior::signal_show() { return _dock_item.signal_show(); } Glib::SignalProxy0 DockBehavior::signal_hide() { return _dock_item.signal_hide(); } Glib::SignalProxy1 DockBehavior::signal_delete_event() { return _dock_item.signal_delete_event(); } Glib::SignalProxy0 DockBehavior::signal_drag_begin() { return _dock_item.signal_drag_begin(); } Glib::SignalProxy1 DockBehavior::signal_drag_end() { return _dock_item.signal_drag_end(); } } // namespace Behavior } // namespace Dialog } // namespace UI } // namespace Inkscape /* Local Variables: mode:c++ c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :