From da15593ce819c0c0fa2c2adaddebde9de7e0f62c Mon Sep 17 00:00:00 2001 From: gustav_b Date: Sun, 2 Sep 2007 22:31:56 +0000 Subject: [PATCH] Fixes for transient dialogs in win32. --- src/ui/dialog/dialog.cpp | 12 ++++- src/ui/dialog/dialog.h | 10 ++++- src/ui/dialog/dock-behavior.cpp | 68 ++++++++++++++++++++++++++--- src/ui/dialog/dock-behavior.h | 3 +- src/ui/dialog/floating-behavior.cpp | 9 ---- src/ui/widget/dock-item.cpp | 8 ++-- src/ui/widget/dock-item.h | 5 +-- 7 files changed, 88 insertions(+), 27 deletions(-) diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp index 16124d9f5..a0557827c 100644 --- a/src/ui/dialog/dialog.cpp +++ b/src/ui/dialog/dialog.cpp @@ -40,14 +40,22 @@ namespace Inkscape { namespace UI { namespace Dialog { -static void +void sp_retransientize (Inkscape::Application *inkscape, SPDesktop *desktop, gpointer dlgPtr) { Dialog *dlg = (Dialog *)dlgPtr; dlg->onDesktopActivated (desktop); } -static void +gboolean +sp_retransientize_again (gpointer dlgPtr) +{ + Dialog *dlg = (Dialog *)dlgPtr; + dlg->retransientize_suppress = false; + return FALSE; // so that it is only called once +} + +void sp_dialog_shutdown (GtkObject *object, gpointer dlgPtr) { Dialog *dlg = (Dialog *)dlgPtr; diff --git a/src/ui/dialog/dialog.h b/src/ui/dialog/dialog.h index 7530b9a35..50b69caa4 100644 --- a/src/ui/dialog/dialog.h +++ b/src/ui/dialog/dialog.h @@ -21,15 +21,23 @@ #include "dock-behavior.h" #include "floating-behavior.h" -namespace Inkscape { class Selection; } class SPDesktop; +namespace Inkscape { +class Selection; +class Application; +} + namespace Inkscape { namespace UI { namespace Dialog { enum BehaviorType { FLOATING, DOCK }; +void sp_retransientize(Inkscape::Application *inkscape, SPDesktop *desktop, gpointer dlgPtr); +gboolean sp_retransientize_again(gpointer dlgPtr); +void sp_dialog_shutdown(GtkObject *object, gpointer dlgPtr); + class Dialog { public: diff --git a/src/ui/dialog/dock-behavior.cpp b/src/ui/dialog/dock-behavior.cpp index 188fc6fb1..5f600db46 100644 --- a/src/ui/dialog/dock-behavior.cpp +++ b/src/ui/dialog/dock-behavior.cpp @@ -23,6 +23,7 @@ #include "verbs.h" #include "dialog.h" #include "prefs-utils.h" +#include "dialogs/dialog-events.h" #include #include @@ -49,7 +50,12 @@ DockBehavior::DockBehavior(Dialog& dialog) : // Connect signals _signal_hide_connection = signal_hide().connect(sigc::mem_fun(*this, &Inkscape::UI::Dialog::Behavior::DockBehavior::_onHide)); signal_response().connect(sigc::mem_fun(_dialog, &Inkscape::UI::Dialog::Dialog::on_response)); - signal_drag_end().connect(sigc::mem_fun(*this, &Inkscape::UI::Dialog::Behavior::DockBehavior::_onDragEnd)); + _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() @@ -230,12 +236,14 @@ DockBehavior::_onHide() } void -DockBehavior::_onDragEnd(bool) +DockBehavior::_onStateChanged(Widget::DockItem::State prev_state, + Widget::DockItem::State new_state) { - Widget::DockItem::State prev_state = _dock_item.getPrevState(), state = _dock_item.getState(); - - if (prev_state != state) { - prefs_set_int_attribute (_dialog._prefs_path, "state", state); + prefs_set_int_attribute (_dialog._prefs_path, "state", new_state); + + if (new_state == Widget::DockItem::FLOATING_STATE) { + if (Gtk::Window *floating_win = _dock_item.getWindow()) + sp_transientize(GTK_WIDGET(floating_win->gobj())); } } @@ -267,6 +275,54 @@ DockBehavior::onShutdown() void DockBehavior::onDesktopActivated(SPDesktop *desktop) { + gint transient_policy = prefs_get_int_attribute_limited ( "options.transientpolicy", "value", 1, 0, 2); + +#ifdef WIN32 // FIXME: Temporary Win32 special code to enable transient dialogs + if (prefs_get_int_attribute ( "options.dialogsontopwin32", "value", 0)) + transient_policy = 2; + else + return; +#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 + gtk_timeout_add (120, (GtkFunction) sp_retransientize_again, (gpointer) floating_win); + } } diff --git a/src/ui/dialog/dock-behavior.h b/src/ui/dialog/dock-behavior.h index 75bd14be4..01d95dd8c 100644 --- a/src/ui/dialog/dock-behavior.h +++ b/src/ui/dialog/dock-behavior.h @@ -91,8 +91,7 @@ private: void _onHide(); bool _onDeleteEvent(GdkEventAny *event); void _onResponse(int response_id); - void _onDragBegin(); - void _onDragEnd(bool cancelled); + void _onStateChanged(Widget::DockItem::State prev_state, Widget::DockItem::State new_state); bool _onKeyPress(GdkEventKey *event); sigc::connection _signal_hide_connection; diff --git a/src/ui/dialog/floating-behavior.cpp b/src/ui/dialog/floating-behavior.cpp index b6b6949da..79f5d08fb 100644 --- a/src/ui/dialog/floating-behavior.cpp +++ b/src/ui/dialog/floating-behavior.cpp @@ -29,15 +29,6 @@ namespace UI { namespace Dialog { namespace Behavior { -static gboolean -sp_retransientize_again (gpointer dlgPtr) -{ - Dialog *dlg = (Dialog *)dlgPtr; - dlg->retransientize_suppress = false; - return FALSE; // so that it is only called once -} - - FloatingBehavior::FloatingBehavior(Dialog& dialog) : Behavior(dialog), _d (new Gtk::Dialog(_dialog._title)) diff --git a/src/ui/widget/dock-item.cpp b/src/ui/widget/dock-item.cpp index 1e232cb4e..97f11f56e 100644 --- a/src/ui/widget/dock-item.cpp +++ b/src/ui/widget/dock-item.cpp @@ -222,8 +222,8 @@ DockItem::present() void DockItem::get_position(int& x, int& y) { - if (_getWindow()) { - _getWindow()->get_position(x, y); + if (getWindow()) { + getWindow()->get_position(x, y); } else { x = _x; y = _y; @@ -392,7 +392,7 @@ DockItem::_onKeyPress(GdkEventKey *event) void DockItem::_onStateChanged(State prev_state, State new_state) { - _window = _getWindow(); + _window = getWindow(); if (new_state == FLOATING_STATE) { _window->signal_hide().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onHideWindow)); @@ -411,7 +411,7 @@ DockItem::_onDeleteEvent(GdkEventAny *event) Gtk::Window * -DockItem::_getWindow() +DockItem::getWindow() { g_return_val_if_fail(_gdl_dock_item, 0); Gtk::Container *parent = getWidget().get_parent(); diff --git a/src/ui/widget/dock-item.h b/src/ui/widget/dock-item.h index 55a280767..f4e403e34 100644 --- a/src/ui/widget/dock-item.h +++ b/src/ui/widget/dock-item.h @@ -70,6 +70,8 @@ public: State getPrevState() const; Placement getPlacement() const; + Gtk::Window *getWindow(); //< gives the parent window, if the dock item has one (i.e. it's floating) + void addButton(Gtk::Button *button, int response_id); void hide(); @@ -131,9 +133,6 @@ private: static gboolean _signal_delete_event_callback(GtkWidget *self, GdkEventAny *event, void *data); static void _signal_drag_end_callback(GtkWidget* self, gboolean p0, void* data); - /** Internal helpers */ - Gtk::Window *_getWindow(); //< gives the parent window, if the dock item has one (i.e. it's floating) - /** In order to emulate a signal_response signal like the one for Gtk::Dialog we inject a new * signal into GdlDockItem. This signal will be emitted when a button in the dock item added * through the addButton(..., response_id) method, is clicked. -- 2.30.2