Code

patch 1734633: option to save window geometry in prefs
authorbuliabyak <buliabyak@users.sourceforge.net>
Mon, 18 Jun 2007 18:52:51 +0000 (18:52 +0000)
committerbuliabyak <buliabyak@users.sourceforge.net>
Mon, 18 Jun 2007 18:52:51 +0000 (18:52 +0000)
12 files changed:
src/desktop.cpp
src/desktop.h
src/interface.cpp
src/preferences-skeleton.h
src/sp-namedview.cpp
src/ui/dialog/inkscape-preferences.cpp
src/ui/dialog/inkscape-preferences.h
src/ui/view/edit-widget-interface.h
src/ui/view/edit-widget.cpp
src/ui/view/edit-widget.h
src/widgets/desktop-widget.cpp
src/widgets/desktop-widget.h

index d9f82934c039c13550c69a7dbee1635c0cba5bde..03373b59e9d22ba605bcfe8ebabb50357936c16d 100644 (file)
@@ -129,7 +129,7 @@ SPDesktop::SPDesktop() :
     zooms_future( 0 ),
     dkey( 0 ),
     number( 0 ),
-    is_fullscreen( false ),
+    window_state(0),
     interaction_disabled_counter( 0 ),
     waiting_cursor( false ),
     guides_active( false ),
@@ -970,6 +970,36 @@ SPDesktop::scroll_to_point (NR::Point const *p, gdouble autoscrollspeed)
     return false;
 }
 
+bool
+SPDesktop::is_iconified()
+{
+    return 0!=(window_state & GDK_WINDOW_STATE_ICONIFIED);
+}
+
+void
+SPDesktop::iconify()
+{
+    _widget->setIconified();
+}
+
+bool
+SPDesktop::is_maximized()
+{
+    return 0!=(window_state & GDK_WINDOW_STATE_MAXIMIZED);
+}
+
+void
+SPDesktop::maximize()
+{
+    _widget->setMaximized();
+}
+
+bool
+SPDesktop::is_fullscreen()
+{
+    return 0!=(window_state & GDK_WINDOW_STATE_FULLSCREEN);
+}
+
 void
 SPDesktop::fullscreen()
 {
index 1ee4d375ea41948e15fa94425d6990fa356d4b10..4c255ecbbb140f9c935c43ec9afe5e423e7534ff 100644 (file)
@@ -99,7 +99,7 @@ struct SPDesktop : public Inkscape::UI::View::View
     GList *zooms_future;
     unsigned int dkey;
     unsigned int number;
-    bool is_fullscreen;
+    guint window_state;
     unsigned int interaction_disabled_counter;
     bool waiting_cursor;
 
@@ -251,6 +251,12 @@ struct SPDesktop : public Inkscape::UI::View::View
     void toggleGrid();
     bool gridsEnabled() { return grids_visible; }
     
+    bool is_iconified();
+    bool is_maximized();
+    bool is_fullscreen();
+
+    void iconify();
+    void maximize();
     void fullscreen();
 
     void registerEditWidget (Inkscape::UI::View::EditWidgetInterface *widget)
index fa41e5898bbe81268ce036ee0cab0ab34b375bfb..ea08f170c65b0cf4c14a69e53a6f3231faf0f927 100644 (file)
@@ -69,6 +69,8 @@ using Inkscape::IO::Base64OutputStream;
 
 /* forward declaration */
 static gint sp_ui_delete(GtkWidget *widget, GdkEvent *event, Inkscape::UI::View::View *view);
+static void sp_ui_state_event(GtkWidget *widget, GdkEventWindowState *event, SPDesktop*desktop);
+
 
 /* Drag and Drop */
 typedef enum {
@@ -125,32 +127,82 @@ SPActionEventVector menu_item_event_vector = {
     sp_ui_menu_item_set_name /* set_name */
 };
 
+static const int MIN_ONSCREEN_DISTANCE = 50;
+
 void
 sp_create_window(SPViewWidget *vw, gboolean editable)
 {
     g_return_if_fail(vw != NULL);
     g_return_if_fail(SP_IS_VIEW_WIDGET(vw));
 
-    GtkWidget *w = sp_window_new("", TRUE);
+    GtkWidget *win = sp_window_new("", TRUE);
 
     if (editable) {
-      g_object_set_data(G_OBJECT(vw), "window", w);
+      g_object_set_data(G_OBJECT(vw), "window", win);
       reinterpret_cast<SPDesktopWidget*>(vw)->window =
-        static_cast<GtkWindow*>((void*)w);
+        static_cast<GtkWindow*>((void*)win);
     }
 
     if (editable) {
-        /* fixme: */
-        gtk_window_set_default_size((GtkWindow *) w, 640, 480);
-        g_object_set_data(G_OBJECT(w), "desktop", SP_DESKTOP_WIDGET(vw)->desktop);
-        g_object_set_data(G_OBJECT(w), "desktopwidget", vw);
-        g_signal_connect(G_OBJECT(w), "delete_event", G_CALLBACK(sp_ui_delete), vw->view);
-        g_signal_connect(G_OBJECT(w), "focus_in_event", G_CALLBACK(sp_desktop_widget_set_focus), vw);
+        SPDesktop* desktop = SP_DESKTOP_WIDGET(vw)->desktop;
+
+        /* fixme: doesn't allow making window any smaller than this */
+        gtk_window_set_default_size((GtkWindow *) win, 640, 480);
+        g_object_set_data(G_OBJECT(win), "desktop", desktop);
+        g_object_set_data(G_OBJECT(win), "desktopwidget", vw);
+        g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(sp_ui_delete), vw->view);
+
+        g_signal_connect(G_OBJECT(win), "window_state_event", G_CALLBACK(sp_ui_state_event), static_cast<SPDesktop*>(vw->view));
+        g_signal_connect(G_OBJECT(win), "focus_in_event", G_CALLBACK(sp_desktop_widget_set_focus), vw);
+
+        gint prefs_geometry = 
+            (2==prefs_get_int_attribute("options.savewindowgeometry", "value", 0));
+        if (prefs_geometry) {
+            gint pw = prefs_get_int_attribute("desktop.geometry", "width", -1);
+            gint ph = prefs_get_int_attribute("desktop.geometry", "height", -1);
+            gint px = prefs_get_int_attribute("desktop.geometry", "x", -1);
+            gint py = prefs_get_int_attribute("desktop.geometry", "y", -1);
+            gint full = prefs_get_int_attribute("desktop.geometry", "fullscreen", 0);
+            gint maxed = prefs_get_int_attribute("desktop.geometry", "maximized", 0);
+            if (pw>0 && ph>0) {
+                gint w = MIN(gdk_screen_width(), pw);
+                gint h = MIN(gdk_screen_height(), ph);
+                gint x = MIN(gdk_screen_width() - MIN_ONSCREEN_DISTANCE, px);
+                gint y = MIN(gdk_screen_height() - MIN_ONSCREEN_DISTANCE, py);
+                if (w>0 && h>0 && x>0 && y>0) {
+                    x = MIN(gdk_screen_width() - w, x);
+                    y = MIN(gdk_screen_height() - h, y);
+                }
+                if (w>0 && h>0) {
+                    desktop->setWindowSize(w, h);
+                }
+
+                // Only restore xy for the first window so subsequent windows don't overlap exactly
+                // with first.  (Maybe rule should be only restore xy if it's different from xy of
+                // other desktops?)
+
+                // Empirically it seems that active_desktop==this desktop only the first time a
+                // desktop is created.
+                if (x>0 && y>0) {
+                    SPDesktop *active_desktop = SP_ACTIVE_DESKTOP;
+                    if (active_desktop == desktop || active_desktop==NULL) {
+                        desktop->setWindowPosition(NR::Point(x, y));
+                    }
+                }
+            }
+            if (maxed) {
+                gtk_window_maximize(GTK_WINDOW(win));
+            }
+            if (full) {
+                gtk_window_fullscreen(GTK_WINDOW(win));
+            }
+        }
+
     } else {
-        gtk_window_set_policy(GTK_WINDOW(w), TRUE, TRUE, TRUE);
+        gtk_window_set_policy(GTK_WINDOW(win), TRUE, TRUE, TRUE);
     }
 
-    gtk_container_add(GTK_CONTAINER(w), GTK_WIDGET(vw));
+    gtk_container_add(GTK_CONTAINER(win), GTK_WIDGET(vw));
     gtk_widget_show(GTK_WIDGET(vw));
 
     if ( completeDropTargets == 0 || completeDropTargetsCount == 0 )
@@ -184,16 +236,16 @@ sp_create_window(SPViewWidget *vw, gboolean editable)
         }
     }
 
-    gtk_drag_dest_set(w,
+    gtk_drag_dest_set(win,
                       GTK_DEST_DEFAULT_ALL,
                       completeDropTargets,
                       completeDropTargetsCount,
                       GdkDragAction(GDK_ACTION_COPY | GDK_ACTION_MOVE));
-    g_signal_connect(G_OBJECT(w),
+    g_signal_connect(G_OBJECT(win),
                      "drag_data_received",
                      G_CALLBACK(sp_ui_drag_data_received),
                      NULL);
-    gtk_widget_show(w);
+    gtk_widget_show(win);
 
     // needed because the first ACTIVATE_DESKTOP was sent when there was no window yet
     inkscape_reactivate_desktop(SP_DESKTOP_WIDGET(vw)->desktop);
@@ -283,6 +335,53 @@ sp_ui_delete(GtkWidget *widget, GdkEvent *event, Inkscape::UI::View::View *view)
     return view->shutdown();
 }
 
+/**
+ *  sp_ui_state_event
+ *
+ *  Called when the window changes its maximize/fullscreen/iconify/pinned state.
+ *  Since GTK doesn't have a way to query this state information directly, we
+ *  record it for the desktop here, and also possibly trigger a layout.
+ */
+static void
+sp_ui_state_event(GtkWidget *widget, GdkEventWindowState *event, SPDesktop* desktop)
+{
+    // Record the desktop window's state
+    desktop->window_state = event->new_window_state;
+
+    // Layout may differ depending on full-screen mode or not
+    GdkWindowState changed = event->changed_mask;
+    if (changed & (GDK_WINDOW_STATE_FULLSCREEN|GDK_WINDOW_STATE_MAXIMIZED)) {
+        desktop->layoutWidget();
+    }
+/*
+    // debug info
+    g_message("State event desktop=0x%p", desktop);
+    GdkWindowState state = event->new_window_state;
+    GdkWindowState changed = event->changed_mask;
+    if (changed & GDK_WINDOW_STATE_WITHDRAWN) {
+        g_message("-- WIDTHDRAWN = %d", 0!=(state&GDK_WINDOW_STATE_WITHDRAWN));
+    }
+    if (changed & GDK_WINDOW_STATE_ICONIFIED) {
+        g_message("-- ICONIFIED = %d", 0!=(state&GDK_WINDOW_STATE_ICONIFIED));
+    }
+    if (changed & GDK_WINDOW_STATE_MAXIMIZED) {
+        g_message("-- MAXIMIZED = %d", 0!=(state&GDK_WINDOW_STATE_MAXIMIZED));
+    }
+    if (changed & GDK_WINDOW_STATE_STICKY) {
+        g_message("-- STICKY = %d", 0!=(state&GDK_WINDOW_STATE_STICKY));
+    }
+    if (changed & GDK_WINDOW_STATE_FULLSCREEN) {
+        g_message("-- FULLSCREEN = %d", 0!=(state&GDK_WINDOW_STATE_FULLSCREEN));
+    }
+    if (changed & GDK_WINDOW_STATE_ABOVE) {
+        g_message("-- ABOVE = %d", 0!=(state&GDK_WINDOW_STATE_ABOVE));
+    }
+    if (changed & GDK_WINDOW_STATE_BELOW) {
+        g_message("-- BELOW = %d", 0!=(state&GDK_WINDOW_STATE_BELOW));
+    }
+*/
+}
+
 /*
  * Some day when the right-click menus are ready to start working
  * smarter with the verbs, we'll need to change this NULL being
@@ -565,7 +664,7 @@ checkitem_toggled(GtkCheckMenuItem *menuitem, gpointer user_data)
     Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(menuitem), "view");
 
     gchar const *pref_path;
-    if (reinterpret_cast<SPDesktop*>(view)->is_fullscreen)
+    if (reinterpret_cast<SPDesktop*>(view)->is_fullscreen())
         pref_path = g_strconcat("fullscreen.", pref, NULL);
     else
         pref_path = g_strconcat("window.", pref, NULL);
@@ -585,7 +684,7 @@ checkitem_update(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
     Inkscape::UI::View::View *view = (Inkscape::UI::View::View *) g_object_get_data(G_OBJECT(menuitem), "view");
 
     gchar const *pref_path;
-    if (static_cast<SPDesktop*>(view)->is_fullscreen)
+    if ((static_cast<SPDesktop*>(view))->is_fullscreen())
         pref_path = g_strconcat("fullscreen.", pref, NULL);
     else
         pref_path = g_strconcat("window.", pref, NULL);
index 30ea64dd018e3bf04fa1a2dec3ac790498d546d5..28b1fe01849f5988591500b58944aeb097bf8cb0 100644 (file)
@@ -216,6 +216,13 @@ static char const preferences_skeleton[] =
 "\n"
 "  <group id=\"desktop\""
 "         style=\"\">\n"
+"    <group\n"
+"       width=\"640\"\n"
+"       height=\"480\"\n"
+"       x=\"0\"\n"
+"       y=\"0\"\n"
+"       fullscreen=\"0\"\n"
+"       id=\"geometry\" />\n"
 "  </group>\n"
 "\n"
 "  <group id=\"devices\">\n"
index ea0e55dc55d06568efac62c45431ac837e0119ed..02783207ea104ae0f29744e4070a82f1ecdd8fe0 100644 (file)
@@ -571,15 +571,16 @@ void SPNamedView::show(SPDesktop *desktop)
 #define MIN_ONSCREEN_DISTANCE 50
 
 /*
- * Restores window geometry from the document settings
+ * Restores window geometry from the document settings or defaults in prefs
  */
 void sp_namedview_window_from_document(SPDesktop *desktop)
 {
     SPNamedView *nv = desktop->namedview;
-    gint save_geometry = prefs_get_int_attribute("options.savewindowgeometry", "value", 0);
+    gint geometry_from_file = 
+        (1==prefs_get_int_attribute("options.savewindowgeometry", "value", 0));
 
-    // restore window size and position
-    if (save_geometry) {
+    // restore window size and position stored with the document
+    if (geometry_from_file) {
         gint w = MIN(gdk_screen_width(), nv->window_width);
         gint h = MIN(gdk_screen_height(), nv->window_height);
         gint x = MIN(gdk_screen_width() - MIN_ONSCREEN_DISTANCE, nv->window_x);
@@ -588,10 +589,12 @@ void sp_namedview_window_from_document(SPDesktop *desktop)
             x = MIN(gdk_screen_width() - w, x);
             y = MIN(gdk_screen_height() - h, y);
         }
-        if (w>0 && h>0)
+        if (w>0 && h>0) {
             desktop->setWindowSize(w, h);
-        if (x>0 && y>0)
+        }
+        if (x>0 && y>0) {
             desktop->setWindowPosition(NR::Point(x, y));
+        }
     }
 
     // restore zoom and view
@@ -641,7 +644,8 @@ void sp_namedview_update_layers_from_document (SPDesktop *desktop)
 
 void sp_namedview_document_from_window(SPDesktop *desktop)
 {
-    gint save_geometry = prefs_get_int_attribute("options.savewindowgeometry", "value", 0);
+    gint save_geometry_in_file = 
+        (1==prefs_get_int_attribute("options.savewindowgeometry", "value", 0));
     Inkscape::XML::Node *view = SP_OBJECT_REPR(desktop->namedview);
     NR::Rect const r = desktop->get_display_area();
 
@@ -653,7 +657,7 @@ void sp_namedview_document_from_window(SPDesktop *desktop)
     sp_repr_set_svg_double(view, "inkscape:cx", r.midpoint()[NR::X]);
     sp_repr_set_svg_double(view, "inkscape:cy", r.midpoint()[NR::Y]);
 
-    if (save_geometry) {
+    if (save_geometry_in_file) {
         gint w, h, x, y;
         desktop->getWindowGeometry(x, y, w, h);
         sp_repr_set_int(view, "inkscape:window-width", w);
index f40197cef5cbbd76cff50dfa7fa03b69295e73d5..5694a3ea3ddd1b3be777a7db061818e893f09f6a 100644 (file)
@@ -414,7 +414,10 @@ void InkscapePreferences::initPageTools()
 
 void InkscapePreferences::initPageWindows()
 {
-    _win_save_geom.init ( _("Save window geometry"), "options.savewindowgeometry", "value", true);
+    _win_save_geom.init ( _("Save and restore window geometry for each document"), "options.savewindowgeometry", "value", 1, true, 0);
+    _win_save_geom_prefs.init ( _("Remember and use last window's geometry"), "options.savewindowgeometry", "value", 2, false, &_win_save_geom);
+    _win_save_geom_off.init ( _("Don't save window geometry"), "options.savewindowgeometry", "value", 0, false, &_win_save_geom);
+
     _win_hide_task.init ( _("Dialogs are hidden in taskbar"), "options.dialogsskiptaskbar", "value", true);
     _win_zoom_resize.init ( _("Zoom when window is resized"), "options.stickyzoom", "value", false);
     _win_show_close.init ( _("Show close button on dialogs"), "dialogs", "showclose", false);
@@ -427,16 +430,14 @@ void InkscapePreferences::initPageWindows()
     _win_ontop_win32.init ( _("Dialogs stay on top (experimental!)"), "options.dialogsontopwin32", "value", false);
 #endif 
 
+    _page_windows.add_group_header( _("Saving window geometry (size and position):"));
+    _page_windows.add_line( false, "", _win_save_geom_off, "", 
+                            _("Let the window manager determine placement of all windows"));
+    _page_windows.add_line( false, "", _win_save_geom_prefs, "", 
+                            _("Remember and use the last window's geometry (saves geometry to user preferences)"));
     _page_windows.add_line( false, "", _win_save_geom, "", 
-                            _("Save the window size and position with each document (only for Inkscape SVG format)"));
-#ifndef WIN32 // FIXME: Temporary Win32 special code to enable transient dialogs
-    _page_windows.add_line( false, "", _win_hide_task, "", 
-                            _("Whether dialog windows are to be hidden in the window manager taskbar"));
-#endif                           
-    _page_windows.add_line( false, "", _win_zoom_resize, "", 
-                            _("Zoom drawing when document window is resized, to keep the same area visible (this is the default which can be changed in any window using the button above the right scrollbar)"));
-    _page_windows.add_line( false, "", _win_show_close, "", 
-                            _("Whether dialog windows have a close button (requires restart)"));
+                            _("Save and restore window geometry for each document (saves geometry in the document)"));
+
     _page_windows.add_group_header( _("Dialogs on top:"));
 #ifndef WIN32 // FIXME: Temporary Win32 special code to enable transient dialogs
     _page_windows.add_line( true, "", _win_ontop_none, "", 
@@ -450,6 +451,15 @@ void InkscapePreferences::initPageWindows()
                             _("Whether dialogs should stay on top of document windows. Read the ReleaseNotes on this issue! (Rightclick the taskbar button and press 'Restore' to bring back a minimized document window)"));
 #endif                            
 
+    _page_windows.add_group_header( _("Miscellaneous:"));
+#ifndef WIN32 // FIXME: Temporary Win32 special code to enable transient dialogs
+    _page_windows.add_line( false, "", _win_hide_task, "", 
+                            _("Whether dialog windows are to be hidden in the window manager taskbar"));
+#endif                           
+    _page_windows.add_line( false, "", _win_zoom_resize, "", 
+                            _("Zoom drawing when document window is resized, to keep the same area visible (this is the default which can be changed in any window using the button above the right scrollbar)"));
+    _page_windows.add_line( false, "", _win_show_close, "", 
+                            _("Whether dialog windows have a close button (requires restart)"));
     this->AddPage(_page_windows, _("Windows"), PREFS_PAGE_WINDOWS);
 }
 
index a088946388f08321a89a9c89ba56e114c133e05c..f2a61d1ba8081e4415cb91caf95c28bd340b5676 100644 (file)
@@ -117,7 +117,8 @@ protected:
     PrefSpinButton  _t_pencil_tolerance;
 
     PrefRadioButton _win_ontop_none, _win_ontop_normal, _win_ontop_agressive;
-    PrefCheckButton _win_save_geom, _win_hide_task, _win_zoom_resize , _win_show_close;
+    PrefRadioButton _win_save_geom_off, _win_save_geom, _win_save_geom_prefs;
+    PrefCheckButton _win_hide_task, _win_zoom_resize , _win_show_close;
 
 // FIXME: Temporary Win32 special code to enable transient dialogs
 #ifdef WIN32 
index 7cc0133d37ee48a4f04ae72a7e8d5f47d1dd8dcf..1df0bff457be70159b44ee9c38841ade52a8d6b0 100644 (file)
@@ -56,6 +56,12 @@ struct EditWidgetInterface
     /// Return mouse position in widget
     virtual NR::Point getPointer() = 0;
     
+    /// Make widget iconified
+    virtual void setIconified() = 0;
+    
+    /// Make widget maximized on screen
+    virtual void setMaximized() = 0;
+    
     /// Make widget fill screen and show it if possible.
     virtual void setFullscreen() = 0;
     
index bac6854a13e873d874e65526fc3a0bee10c7788c..ca298cd5dbd4f3ed4c648a711fa34864aec44e87 100644 (file)
@@ -1167,6 +1167,18 @@ EditWidget::getPointer()
     return NR::Point (x, y);
 }
 
+void
+EditWidget::setIconified()
+{
+    iconify();
+}
+
+void
+EditWidget::setMaximized()
+{
+    maximize();
+}
+
 void
 EditWidget::setFullscreen()
 {
@@ -1426,11 +1438,11 @@ EditWidget::toggleRulers()
     {
         _top_ruler.hide_all();
         _left_ruler.hide_all();
-        prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 0);
+        prefs_set_int_attribute (_desktop->is_fullscreen() ? "fullscreen.rulers" : "window.rulers", "state", 0);
     } else {
         _top_ruler.show_all();
         _left_ruler.show_all();
-        prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 1);
+        prefs_set_int_attribute (_desktop->is_fullscreen() ? "fullscreen.rulers" : "window.rulers", "state", 1);
     }
 }
 
@@ -1441,11 +1453,11 @@ EditWidget::toggleScrollbars()
     {
         _bottom_scrollbar.hide_all();
         _right_scrollbar.hide_all();
-        prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0);
+        prefs_set_int_attribute (_desktop->is_fullscreen() ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0);
     } else {
         _bottom_scrollbar.show_all();
         _right_scrollbar.show_all();
-        prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1);
+        prefs_set_int_attribute (_desktop->is_fullscreen() ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1);
     }
 }
 
index 55a52be4c2a42dfc8c9e01234686d010fcf528a1..bedb94f9804a3504bedd13c17b770fad55320f2f 100644 (file)
@@ -106,6 +106,8 @@ public:
     virtual void setPosition (NR::Point p);
     virtual void setTransient (void*, int);
     virtual NR::Point getPointer();
+    virtual void setIconified();
+    virtual void setMaximized();
     virtual void setFullscreen();
     virtual bool shutdown();
     virtual void destroy();
index 47694518c912019bf0f2a8c664c7db3db6c7f538..9716191ed6b65b61c665ab42bb8bad6bd1bac269 100644 (file)
@@ -84,8 +84,6 @@ static void sp_desktop_widget_realize (GtkWidget *widget);
 
 static gint sp_desktop_widget_event (GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw);
 
-
-
 static void sp_desktop_widget_adjustment_value_changed (GtkAdjustment *adj, SPDesktopWidget *dtw);
 static void sp_desktop_widget_namedview_modified (SPObject *obj, guint flags, SPDesktopWidget *dtw);
 
@@ -555,6 +553,7 @@ bool
 SPDesktopWidget::shutdown()
 {
     g_assert(desktop != NULL);
+
     if (inkscape_is_sole_desktop_for_document(*desktop)) {
         SPDocument *doc = desktop->doc();
         if (sp_document_repr_root(doc)->attribute("sodipodi:modified") != NULL) {
@@ -685,6 +684,28 @@ SPDesktopWidget::shutdown()
         }
     }
 
+    /* Save window geometry to prefs for use as a default.
+     * Use depends on setting of "options.savewindowgeometry".
+     * But we save the info here regardless of the setting.
+     */
+    {
+        gint full = desktop->is_fullscreen() ? 1 : 0;
+        gint maxed = desktop->is_maximized() ? 1 : 0;
+        prefs_set_int_attribute("desktop.geometry", "fullscreen", full);
+        prefs_set_int_attribute("desktop.geometry", "maximized", maxed);
+        gint w, h, x, y;
+        desktop->getWindowGeometry(x, y, w, h);
+        // Don't save geom for maximized windows.  It 
+        // just tells you the current maximized size, which is not
+        // as useful as whatever value it had previously.
+        if (!maxed && !full) {
+            prefs_set_int_attribute("desktop.geometry", "width", w);
+            prefs_set_int_attribute("desktop.geometry", "height", h);
+            prefs_set_int_attribute("desktop.geometry", "x", x);
+            prefs_set_int_attribute("desktop.geometry", "y", y);
+        }
+    }
+
     return FALSE;
 }
 
@@ -750,6 +771,8 @@ SPDesktopWidget::letZoomGrabFocus()
 void
 SPDesktopWidget::getWindowGeometry (gint &x, gint &y, gint &w, gint &h)
 {
+    gboolean vis = GTK_WIDGET_VISIBLE (this);
+
     GtkWindow *window = GTK_WINDOW (gtk_object_get_data (GTK_OBJECT(this), "window"));
     if (window)
     {
@@ -835,20 +858,68 @@ SPDesktopWidget::warnDialog (gchar* text)
     return false;
 }
 
+void
+sp_desktop_widget_iconify(SPDesktopWidget *dtw)
+{
+    GtkWindow *topw = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(dtw->canvas)));
+    if (GTK_IS_WINDOW(topw)) {
+        if (dtw->desktop->is_iconified()) {
+            gtk_window_deiconify(topw);
+        } else {
+            gtk_window_iconify(topw);
+        }
+    }
+}
+
+void
+sp_desktop_widget_maximize(SPDesktopWidget *dtw)
+{
+    GtkWindow *topw = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(dtw->canvas)));
+    if (GTK_IS_WINDOW(topw)) {
+        if (dtw->desktop->is_maximized()) {
+            gtk_window_unmaximize(topw);
+        } else {
+            // Save geometry to prefs before maximizing so that 
+            // something useful is stored there, because GTK doesn't maintain
+            // a separate non-maximized size.
+            if (!dtw->desktop->is_iconified() && !dtw->desktop->is_fullscreen()) 
+            {
+                gint w, h, x, y;
+                dtw->getWindowGeometry(x, y, w, h);
+                prefs_set_int_attribute("desktop.geometry", "width", w);
+                prefs_set_int_attribute("desktop.geometry", "height", h);
+                prefs_set_int_attribute("desktop.geometry", "x", x);
+                prefs_set_int_attribute("desktop.geometry", "y", y);
+            }
+            gtk_window_maximize(topw);
+        }
+    }
+}
+
 void
 sp_desktop_widget_fullscreen(SPDesktopWidget *dtw)
 {
 #ifdef HAVE_GTK_WINDOW_FULLSCREEN
     GtkWindow *topw = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(dtw->canvas)));
     if (GTK_IS_WINDOW(topw)) {
-        if (dtw->desktop->is_fullscreen) {
-            dtw->desktop->is_fullscreen = FALSE;
+        if (dtw->desktop->is_fullscreen()) {
             gtk_window_unfullscreen(topw);
-            sp_desktop_widget_layout (dtw);
+            // widget layout is triggered by the resulting window_state_event
         } else {
-            dtw->desktop->is_fullscreen = TRUE;
+            // Save geometry to prefs before maximizing so that 
+            // something useful is stored there, because GTK doesn't maintain
+            // a separate non-maximized size.
+            if (!dtw->desktop->is_iconified() && !dtw->desktop->is_maximized()) 
+            {
+                gint w, h, x, y;
+                dtw->getWindowGeometry(x, y, w, h);
+                prefs_set_int_attribute("desktop.geometry", "width", w);
+                prefs_set_int_attribute("desktop.geometry", "height", h);
+                prefs_set_int_attribute("desktop.geometry", "x", x);
+                prefs_set_int_attribute("desktop.geometry", "y", y);
+            }
             gtk_window_fullscreen(topw);
-            sp_desktop_widget_layout (dtw);
+            // widget layout is triggered by the resulting window_state_event
         }
     }
 #endif /* HAVE_GTK_WINDOW_FULLSCREEN */
@@ -860,7 +931,7 @@ sp_desktop_widget_fullscreen(SPDesktopWidget *dtw)
 void
 sp_desktop_widget_layout (SPDesktopWidget *dtw)
 {
-    bool fullscreen = dtw->desktop->is_fullscreen;
+    bool fullscreen = dtw->desktop->is_fullscreen();
 
     if (prefs_get_int_attribute (fullscreen ? "fullscreen.menu" : "window.menu", "state", 1) == 0) {
         gtk_widget_hide_all (dtw->menubar);
@@ -1228,11 +1299,11 @@ sp_desktop_widget_toggle_rulers (SPDesktopWidget *dtw)
     if (GTK_WIDGET_VISIBLE (dtw->hruler)) {
         gtk_widget_hide_all (dtw->hruler);
         gtk_widget_hide_all (dtw->vruler);
-        prefs_set_int_attribute (dtw->desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 0);
+        prefs_set_int_attribute (dtw->desktop->is_fullscreen() ? "fullscreen.rulers" : "window.rulers", "state", 0);
     } else {
         gtk_widget_show_all (dtw->hruler);
         gtk_widget_show_all (dtw->vruler);
-        prefs_set_int_attribute (dtw->desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 1);
+        prefs_set_int_attribute (dtw->desktop->is_fullscreen() ? "fullscreen.rulers" : "window.rulers", "state", 1);
     }
 }
 
@@ -1242,11 +1313,11 @@ sp_desktop_widget_toggle_scrollbars (SPDesktopWidget *dtw)
     if (GTK_WIDGET_VISIBLE (dtw->hscrollbar)) {
         gtk_widget_hide_all (dtw->hscrollbar);
         gtk_widget_hide_all (dtw->vscrollbar_box);
-        prefs_set_int_attribute (dtw->desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0);
+        prefs_set_int_attribute (dtw->desktop->is_fullscreen() ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0);
     } else {
         gtk_widget_show_all (dtw->hscrollbar);
         gtk_widget_show_all (dtw->vscrollbar_box);
-        prefs_set_int_attribute (dtw->desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1);
+        prefs_set_int_attribute (dtw->desktop->is_fullscreen() ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1);
     }
 }
 
index 0514dd39389a1207186adb109756e5b7aacfabec..ef70a21d1a2a81070225bd59f7523a6c9103de46 100644 (file)
@@ -35,6 +35,8 @@ void sp_desktop_widget_destroy (SPDesktopWidget* dtw);
 gint sp_desktop_widget_set_focus(GtkWidget *widget, GdkEvent *event, SPDesktopWidget *dtw);
 
 void sp_desktop_widget_show_decorations(SPDesktopWidget *dtw, gboolean show);
+void sp_desktop_widget_iconify(SPDesktopWidget *dtw);
+void sp_desktop_widget_maximize(SPDesktopWidget *dtw);
 void sp_desktop_widget_fullscreen(SPDesktopWidget *dtw);
 void sp_desktop_widget_layout(SPDesktopWidget *dtw);
 void sp_desktop_widget_update_zoom(SPDesktopWidget *dtw);
@@ -127,6 +129,10 @@ struct SPDesktopWidget {
             { _dtw->setWindowTransient (p, transient_policy); }
         virtual NR::Point getPointer()
             { return _dtw->window_get_pointer(); }
+        virtual void setIconified()
+            { sp_desktop_widget_iconify (_dtw); }
+        virtual void setMaximized()
+            { sp_desktop_widget_maximize (_dtw); }
         virtual void setFullscreen()
             { sp_desktop_widget_fullscreen (_dtw); }
         virtual bool shutdown()