Merge lp:~philip.scott/granite/saved-state into lp:~elementary-pantheon/granite/granite

Proposed by Felipe Escoto on 2016-12-30
Status: Work in progress
Proposed branch: lp:~philip.scott/granite/saved-state
Merge into: lp:~elementary-pantheon/granite/granite
Diff against target: 215 lines (+137/-3)
5 files modified
CMakeLists.txt (+1/-0)
data/CMakeLists.txt (+3/-0)
data/io.elementary.granite.gschema.xml (+19/-0)
demo/GraniteDemo.vala (+0/-1)
lib/Application.vala (+114/-2)
To merge this branch: bzr merge lp:~philip.scott/granite/saved-state
Reviewer Review Type Date Requested Status
elementary Pantheon team 2016-12-30 Pending
Review via email: mp+313923@code.launchpad.net

Commit message

Fixes bug #1475825: Window states are saved inconsistently.

Description of the change

Saving state is implemented directly in Application class using it's app_id to get the correct schema

Based from: https://code.launchpad.net/~donadigo/granite/saved-state-in-appclass/+merge/290085

To post a comment you must log in.
lp:~philip.scott/granite/saved-state updated on 2016-12-30
1020. By Felipe Escoto on 2016-12-30

Save app state

Unmerged revisions

1020. By Felipe Escoto on 2016-12-30

Save app state

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2016-08-06 23:40:54 +0000
3+++ CMakeLists.txt 2016-12-30 17:37:06 +0000
4@@ -78,3 +78,4 @@
5 add_subdirectory (doc)
6 add_subdirectory (po)
7 add_subdirectory (icons)
8+add_subdirectory (data)
9
10=== added directory 'data'
11=== added file 'data/CMakeLists.txt'
12--- data/CMakeLists.txt 1970-01-01 00:00:00 +0000
13+++ data/CMakeLists.txt 2016-12-30 17:37:06 +0000
14@@ -0,0 +1,3 @@
15+include (GSettings)
16+
17+add_schema (io.elementary.granite.gschema.xml)
18
19=== added file 'data/io.elementary.granite.gschema.xml'
20--- data/io.elementary.granite.gschema.xml 1970-01-01 00:00:00 +0000
21+++ data/io.elementary.granite.gschema.xml 2016-12-30 17:37:06 +0000
22@@ -0,0 +1,19 @@
23+<schemalist>
24+ <schema path="/io/elementary/granite/saved-state/" id="io.elementary.granite.saved_state" gettext-domain="granite">
25+ <key type="b" name="save-state">
26+ <default>true</default>
27+ <summary>Master control for saving and loading window states of all granite apps</summary>
28+ </key>
29+ <child name="app" schema="io.elementary.granite.saved_state.app" />
30+ </schema>
31+ <schema id="io.elementary.granite.saved_state.app" gettext-domain="granite">
32+ <child name="app" schema="io.elementary.granite.saved_state.app" />
33+ <key name="saved-state" type="(iiiiu)">
34+ <default>(-1,-1,700,500,0)</default>
35+ <summary>The saved state of the window.</summary>
36+ <description>The saved width of the window.
37+ The values represent in the respective order: (x, y, w, h, state)
38+ State = (0 = Normal, 1 = Maximized, 2 = Fullscreen).</description>
39+ </key>
40+ </schema>
41+</schemalist>
42
43=== modified file 'demo/GraniteDemo.vala'
44--- demo/GraniteDemo.vala 2016-09-29 01:45:59 +0000
45+++ demo/GraniteDemo.vala 2016-12-30 17:37:06 +0000
46@@ -66,7 +66,6 @@
47
48 public override void activate () {
49 window = new Gtk.Window ();
50- window.window_position = Gtk.WindowPosition.CENTER;
51 add_window (window);
52
53 main_stack = new Gtk.Stack ();
54
55=== modified file 'lib/Application.vala'
56--- lib/Application.vala 2016-06-09 01:28:31 +0000
57+++ lib/Application.vala 2016-12-30 17:37:06 +0000
58@@ -35,6 +35,16 @@
59 * to create a great deal of an app's functionality.
60 */
61 public abstract class Application : Gtk.Application {
62+ private const string SETTINGS_ID = "io.elementary.granite.saved_state.app";
63+ private const string APP_SETTINGS_PATH = "/io/elementary/granite/saved_state/app/%s/";
64+ private const string SETTINGS_KEY_NAME = "saved-state";
65+
66+ private enum WindowState {
67+ NORMAL = 0,
68+ MAXIMIZED = 1,
69+ FULLSCREEN = 2,
70+ MAXIMIZED_FULLSCREEN = 3
71+ }
72
73 public string build_data_dir;
74 public string build_pkg_data_dir;
75@@ -139,6 +149,8 @@
76 public string about_license;
77 public License about_license_type;
78
79+ private HashTable<Gtk.Window, ulong> window_handlers = new HashTable<Gtk.Window, ulong> (null, null);
80+
81 /**
82 * This creates a new Application class
83 */
84@@ -161,6 +173,9 @@
85
86 add_actions ();
87
88+ window_added.connect (on_window_added);
89+ window_removed.connect (on_window_removed);
90+
91 // Deprecated
92 Granite.app = this;
93 }
94@@ -205,6 +220,66 @@
95 return base.run (args);
96 }
97
98+ private GLib.Settings? state_settings = null;
99+ private void on_window_added (Gtk.Window window) {
100+ if (application_id == null) {
101+ return;
102+ }
103+
104+ var schema = SettingsSchemaSource.get_default ().lookup (SETTINGS_ID, false);
105+ if (schema == null) {
106+ return;
107+ }
108+
109+ state_settings = new GLib.Settings.full (schema, null, APP_SETTINGS_PATH.printf (application_id));
110+ if (state_settings == null) {
111+ return;
112+ }
113+
114+ var tuple = state_settings.get_value (SETTINGS_KEY_NAME);
115+
116+ int x, y, width, height;
117+ uint state;
118+ tuple.@get ("(iiiiu)",
119+ out x,
120+ out y,
121+ out width,
122+ out height,
123+ out state);
124+
125+ if (x != -1 && y != -1) {
126+ window.move (x, y);
127+ }
128+
129+ window.resize (width, height);
130+ switch ((WindowState)state) {
131+ case WindowState.MAXIMIZED:
132+ window.maximize ();
133+ break;
134+ case WindowState.FULLSCREEN:
135+ window.fullscreen ();
136+ break;
137+ case WindowState.MAXIMIZED_FULLSCREEN:
138+ window.maximize ();
139+ window.fullscreen ();
140+ break;
141+ default:
142+ window.unfullscreen ();
143+ window.unmaximize ();
144+ break;
145+ }
146+
147+ window_handlers.insert (window, window.delete_event.connect (on_window_delete_event));
148+ }
149+
150+ private void on_window_removed (Gtk.Window window) {
151+ if (!window_handlers.contains (window)) {
152+ return;
153+ }
154+
155+ window.disconnect (window_handlers.@get (window));
156+ }
157+
158 protected static bool DEBUG = false;
159 protected static bool ABOUT = false;
160
161@@ -215,9 +290,9 @@
162 };
163
164 protected virtual void set_options () {
165-
166- if (DEBUG)
167+ if (DEBUG) {
168 Logger.DisplayLevel = LogLevel.DEBUG;
169+ }
170 }
171
172 /**
173@@ -333,5 +408,42 @@
174 Gtk.main ();
175 }
176 }
177+
178+ private WindowState get_window_state (Gtk.Widget widget) {
179+ var window = widget.get_window ();
180+ if ((window.get_state () & Gdk.WindowState.MAXIMIZED) != 0) {
181+ if ((window.get_state () & Gdk.WindowState.FULLSCREEN) != 0) {
182+ return WindowState.MAXIMIZED_FULLSCREEN;
183+ } else {
184+ return WindowState.MAXIMIZED;
185+ }
186+ } else if ((window.get_state () & Gdk.WindowState.FULLSCREEN) != 0) {
187+ return WindowState.FULLSCREEN;
188+ }
189+
190+ return WindowState.NORMAL;
191+ }
192+
193+ private bool on_window_delete_event (Gtk.Widget widget, Gdk.EventAny event) {
194+ if (this.state_settings == null) {
195+ return false;
196+ }
197+
198+ int x, y, width, height;
199+
200+ ((Gtk.Window)widget).get_size (out width, out height);
201+ ((Gtk.Window)widget).get_position (out x, out y);
202+
203+ var v_x = new GLib.Variant.int32 (x);
204+ var v_y = new GLib.Variant.int32 (y);
205+ var v_width = new GLib.Variant.int32 (width);
206+ var v_height = new GLib.Variant.int32 (height);
207+ var v_state = new GLib.Variant.uint32 ((uint32) get_window_state (widget));
208+
209+ var tuple = new GLib.Variant.tuple ({ v_x, v_y, v_width, v_height, v_state });
210+ state_settings.set_value (SETTINGS_KEY_NAME, tuple);
211+
212+ return false;
213+ }
214 }
215 }

Subscribers

People subscribed via source and target branches