Merge lp:~roryj/gala/maskcorners-plugin into lp:gala

Proposed by Rory
Status: Merged
Approved by: Rico Tzschichholz
Approved revision: 430
Merged at revision: 430
Proposed branch: lp:~roryj/gala/maskcorners-plugin
Merge into: lp:gala
Diff against target: 322 lines (+278/-0)
6 files modified
configure.ac (+1/-0)
data/org.pantheon.desktop.gala.gschema.xml.in.in (+21/-0)
plugins/Makefile.am (+1/-0)
plugins/maskcorners/Main.vala (+171/-0)
plugins/maskcorners/Makefile.am (+59/-0)
plugins/maskcorners/Settings.vala (+25/-0)
To merge this branch: bzr merge lp:~roryj/gala/maskcorners-plugin
Reviewer Review Type Date Requested Status
Rico Tzschichholz Approve
Danielle Foré Approve
Review via email: mp+246855@code.launchpad.net

Commit message

Implement Mask Corners plugin.

Description of the change

Implement Mask Corners plugin.

By default, corners are masked on all monitors and are disabled when an app goes fullscreen.

To post a comment you must log in.
Revision history for this message
Danielle Foré (danrabbit) wrote :

So this is pretty pimp. Very subtle. Some things I noticed:

* The little nudge feedback when attempting to move past the last workspace is not masked.
* When you zoom back in from multi-tasking view, you can see the workspace preview is not masked.
* Any radius over 4 is broken

Another question though: Does this plugin need to be shipped with Gala? There's currently no mechanism for enabling and disabling plugins in Gala. Maybe it would be better to ship as a separate package and let the package manager be the plugin manager through the "enhances" attribute.

review: Needs Fixing
Revision history for this message
Danielle Foré (danrabbit) wrote :

I think a sane upper limit should be set on the radius. Currently you can set ridiculous sizes like 800. I think after 32 you start having some issues with like not being able to click DE elements.

Revision history for this message
Rory (roryj) wrote :

I will have a look into the multitasking view issues, but that will require making changes in MultitaskingView, not this plugin (for which I may need Tom Beckmann's help!).

With the latest commit, changing the radius should work.

I have mainly been following what Tom did with his alternate-alt-tab plugin, but the way gala plugins are currently implemented, gala must be built with the plugin so the plugin cannot be packaged separately.

Revision history for this message
Danielle Foré (danrabbit) wrote :

Been using this with 6px radius. Very cool. I like it a lot

review: Approve
Revision history for this message
Rico Tzschichholz (ricotz) wrote :

Make the codestyle match gala's source.

review: Needs Fixing
Revision history for this message
Rory (roryj) wrote :

Have change the codestyle to match gala's source.

I would be interested to know why gala has a different codestyle to other elementary projects and the official codestyle doc.

Revision history for this message
Rico Tzschichholz (ricotz) wrote :

Avoid doing the same operation/thing multiple times in a method.

Cache external objects in "unowned local vars" if possible and reuse them. (e.g. wm.get_screen())

Cache local values and reuse them. (e.g. *.to_string())

I would prefer printf syntax to enforce type-safety. (e.g. "bla %i-%s".printf (int, string))

Tranforming "if COND { LOGIC } ... return" into "if !COND return; LOGIC" often avoids to indent.

Keep code itself sorted if possible (CONST, STATIC, CTOR, construct, DTOR, public methods, private methods) (quite often reasonable to do)

Lists in Makefiles are usually sorted alphabetically. (configure.ac and plugins/Makefile.am)

Be consistent with your coding paradigms.

In the end squash your branch into one commit.

review: Needs Fixing
Revision history for this message
Rico Tzschichholz (ricotz) wrote :

I am also not a fan of explicitly using "private" just omit it. This make it even more distinguishable from public ones, imo.

Revision history for this message
Rico Tzschichholz (ricotz) wrote :

Instead of creating 4 separate actors for every corner. Better create one and use rotated ClutterClones of it.

review: Needs Fixing
Revision history for this message
Rico Tzschichholz (ricotz) wrote :

Also there is the one-class-per-file convention.

Revision history for this message
Rory (roryj) wrote :

I think I've implemented everything you stated. Thank you very much for the help! :D

lp:~roryj/gala/maskcorners-plugin updated
430. By Rory

Implement Mask Corners plugin

Revision history for this message
Rico Tzschichholz (ricotz) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'configure.ac'
--- configure.ac 2015-01-03 19:55:40 +0000
+++ configure.ac 2015-02-05 20:16:27 +0000
@@ -257,6 +257,7 @@
257data/icons/Makefile257data/icons/Makefile
258vapi/Makefile258vapi/Makefile
259plugins/Makefile259plugins/Makefile
260plugins/maskcorners/Makefile
260plugins/notify/Makefile261plugins/notify/Makefile
261plugins/zoom/Makefile262plugins/zoom/Makefile
262po/Makefile.in263po/Makefile.in
263264
=== modified file 'data/org.pantheon.desktop.gala.gschema.xml.in.in'
--- data/org.pantheon.desktop.gala.gschema.xml.in.in 2015-01-04 09:37:05 +0000
+++ data/org.pantheon.desktop.gala.gschema.xml.in.in 2015-02-05 20:16:27 +0000
@@ -237,4 +237,25 @@
237 <_description>Structure: ['{APP-NAME}:{PRIORITY (show/hide)},{SOUNDS on/off}', ...]</_description>237 <_description>Structure: ['{APP-NAME}:{PRIORITY (show/hide)},{SOUNDS on/off}', ...]</_description>
238 </key>238 </key>
239 </schema>239 </schema>
240
241 <schema path="/org/pantheon/desktop/gala/mask-corners/" id="org.pantheon.desktop.gala.mask-corners" gettext-domain="@GETTEXT_PACKAGE@">
242 <key type="b" name="enable">
243 <default>true</default>
244 <_summary>Enable rounded corner mask</_summary>
245 </key>
246 <key type="i" name="corner-radius">
247 <default>4</default>
248 <range min="1" max="32"/>
249 <_summary>Corner radius</_summary>
250 </key>
251 <key type="b" name="disable-on-fullscreen">
252 <default>true</default>
253 <_summary>Disable corner mask on fullscreen</_summary>
254 <description>If enabled, when an application is fullscreen (fills the monitor), the corner masks will be disabled on that monitor.</description>
255 </key>
256 <key type="b" name="only-on-primary">
257 <default>false</default>
258 <_summary>Only show corner masks on primary monitor</_summary>
259 </key>
260 </schema>
240</schemalist>261</schemalist>
241262
=== modified file 'plugins/Makefile.am'
--- plugins/Makefile.am 2014-07-18 08:24:26 +0000
+++ plugins/Makefile.am 2015-02-05 20:16:27 +0000
@@ -1,4 +1,5 @@
1SUBDIRS = \1SUBDIRS = \
2 maskcorners \
2 notify \3 notify \
3 zoom \4 zoom \
4 $(NULL)5 $(NULL)
56
=== added directory 'plugins/maskcorners'
=== added file 'plugins/maskcorners/Main.vala'
--- plugins/maskcorners/Main.vala 1970-01-01 00:00:00 +0000
+++ plugins/maskcorners/Main.vala 2015-02-05 20:16:27 +0000
@@ -0,0 +1,171 @@
1//
2// Copyright (C) 2015 Rory J Sanderson
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16//
17
18using Clutter;
19using Meta;
20
21namespace Gala.Plugins.MaskCorners
22{
23 public class Main : Gala.Plugin
24 {
25 Gala.WindowManager? wm = null;
26 Screen screen;
27 Settings settings;
28
29 List<Actor>[] cornermasks;
30 int corner_radius = 4;
31
32 public override void initialize (Gala.WindowManager wm)
33 {
34 this.wm = wm;
35 screen = wm.get_screen ();
36 settings = Settings.get_default ();
37
38 setup_cornermasks ();
39
40 settings.changed.connect (resetup_cornermasks);
41 }
42
43 public override void destroy ()
44 {
45 destroy_cornermasks ();
46 }
47
48 void setup_cornermasks ()
49 {
50 if (!settings.enable)
51 return;
52
53 int n_monitors = screen.get_n_monitors ();
54 cornermasks = new List<Actor>[n_monitors];
55 corner_radius = settings.corner_radius;
56
57 if (settings.only_on_primary) {
58 add_cornermasks (screen.get_primary_monitor ());
59 } else {
60 for (int m = 0; m < n_monitors; m++)
61 add_cornermasks (m);
62 }
63
64 if (settings.disable_on_fullscreen)
65 screen.in_fullscreen_changed.connect (fullscreen_changed);
66
67 screen.monitors_changed.connect (resetup_cornermasks);
68 }
69
70 void destroy_cornermasks ()
71 {
72 screen.monitors_changed.disconnect (resetup_cornermasks);
73 screen.in_fullscreen_changed.disconnect (fullscreen_changed);
74
75 foreach (unowned List<Actor> list in cornermasks) {
76 foreach (Actor actor in list)
77 actor.destroy ();
78 }
79 }
80
81 void resetup_cornermasks ()
82 {
83 destroy_cornermasks ();
84 setup_cornermasks ();
85 }
86
87 void fullscreen_changed ()
88 {
89 for (int i = 0; i < screen.get_n_monitors (); i++) {
90 foreach (Actor actor in cornermasks[i]) {
91 if (screen.get_monitor_in_fullscreen (i))
92 actor.hide ();
93 else
94 actor.show ();
95 }
96 }
97 }
98
99 void add_cornermasks (int monitor_no)
100 {
101 var monitor_geometry = screen.get_monitor_geometry (monitor_no);
102
103 Canvas canvas = new Canvas ();
104 canvas.set_size (corner_radius, corner_radius);
105 canvas.draw.connect (draw_cornermask);
106 canvas.invalidate ();
107
108 Actor actor = new Actor ();
109 actor.set_content (canvas);
110 actor.set_size (corner_radius, corner_radius);
111 actor.set_position (monitor_geometry.x, monitor_geometry.y);
112 actor.set_pivot_point ((float) 0.5, (float) 0.5);
113
114 cornermasks[monitor_no].append (actor);
115 wm.stage.add_child (actor);
116
117 for (int p = 1; p < 4; p++) {
118 Clone clone = new Clone (actor);
119 clone.rotation_angle_z = p * 90;
120
121 switch (p) {
122 case 1:
123 clone.set_position (monitor_geometry.x + monitor_geometry.width, monitor_geometry.y);
124 break;
125 case 2:
126 clone.set_position (monitor_geometry.x + monitor_geometry.width, monitor_geometry.y + monitor_geometry.height);
127 break;
128 case 3:
129 clone.set_position (monitor_geometry.x, monitor_geometry.y + monitor_geometry.height);
130 break;
131 }
132
133 cornermasks[monitor_no].append (clone);
134 wm.stage.add_child (clone);
135 }
136 }
137
138 bool draw_cornermask (Cairo.Context context)
139 {
140 var buffer = new Granite.Drawing.BufferSurface (corner_radius, corner_radius);
141 var buffer_context = buffer.context;
142
143 buffer_context.arc (corner_radius, corner_radius, corner_radius, Math.PI, 1.5 * Math.PI);
144 buffer_context.line_to (0, 0);
145 buffer_context.line_to (0, corner_radius);
146 buffer_context.set_source_rgb (0, 0, 0);
147 buffer_context.fill ();
148
149 context.set_operator (Cairo.Operator.CLEAR);
150 context.paint ();
151 context.set_operator (Cairo.Operator.OVER);
152 context.set_source_surface (buffer.surface, 0, 0);
153 context.paint ();
154
155 return true;
156 }
157 }
158}
159
160public Gala.PluginInfo register_plugin ()
161{
162 return
163 {
164 "Mask Corners",
165 "Gala Developers",
166 typeof (Gala.Plugins.MaskCorners.Main),
167 Gala.PluginFunction.ADDITION,
168 Gala.LoadPriority.IMMEDIATE
169 };
170}
171
0172
=== added file 'plugins/maskcorners/Makefile.am'
--- plugins/maskcorners/Makefile.am 1970-01-01 00:00:00 +0000
+++ plugins/maskcorners/Makefile.am 2015-02-05 20:16:27 +0000
@@ -0,0 +1,59 @@
1include $(top_srcdir)/Makefile.common
2
3VAPIDIR = $(top_srcdir)/vapi
4
5BUILT_SOURCES = libgala_maskcorners_la_vala.stamp
6
7libgala_maskcorners_la_LTLIBRARIES = libgala-maskcorners.la
8
9libgala_maskcorners_ladir = $(pkglibdir)/plugins
10
11libgala_maskcorners_la_LDFLAGS = \
12 $(PLUGIN_LDFLAGS) \
13 $(GALA_CORE_LDFLAGS) \
14 $(top_builddir)/lib/libgala.la \
15 $(NULL)
16
17libgala_maskcorners_la_CFLAGS = \
18 $(GALA_CORE_CFLAGS) \
19 -include config.h \
20 -w \
21 -I$(top_builddir)/lib \
22 $(NULL)
23
24libgala_maskcorners_la_VALAFLAGS = \
25 $(GALA_CORE_VALAFLAGS) \
26 $(top_builddir)/lib/gala.vapi \
27 --vapidir $(VAPIDIR) \
28 $(VAPIDIR)/config.vapi \
29 $(NULL)
30
31libgala_maskcorners_la_LIBADD = \
32 $(GALA_CORE_LIBS) \
33 $(NULL)
34
35libgala_maskcorners_la_VALASOURCES = \
36 Main.vala \
37 Settings.vala \
38 $(NULL)
39
40nodist_libgala_maskcorners_la_SOURCES = \
41 $(BUILT_SOURCES) \
42 $(libgala_maskcorners_la_VALASOURCES:.vala=.c) \
43 $(NULL)
44
45libgala_maskcorners_la_vala.stamp: $(libgala_maskcorners_la_VALASOURCES)
46 $(AM_V_VALA)$(VALAC) \
47 $(libgala_maskcorners_la_VALAFLAGS) \
48 -C \
49 $(filter %.vala %.c,$^)
50 $(AM_V_at)touch $@
51
52CLEANFILES = \
53 $(nodist_libgala_maskcorners_la_SOURCES) \
54 $(NULL)
55
56EXTRA_DIST = \
57 $(libgala_maskcorners_la_VALASOURCES) \
58 $(NULL)
59
060
=== added file 'plugins/maskcorners/Settings.vala'
--- plugins/maskcorners/Settings.vala 1970-01-01 00:00:00 +0000
+++ plugins/maskcorners/Settings.vala 2015-02-05 20:16:27 +0000
@@ -0,0 +1,25 @@
1namespace Gala.Plugins.MaskCorners
2{
3 class Settings : Granite.Services.Settings
4 {
5 static Settings? instance = null;
6
7 public static Settings get_default ()
8 {
9 if (instance == null)
10 instance = new Settings ();
11
12 return instance;
13 }
14
15 public bool enable { get; set; default = true; }
16 public int corner_radius { get; set; default = 4; }
17 public bool disable_on_fullscreen { get; set; default = true; }
18 public bool only_on_primary { get; set; default = false; }
19
20 Settings ()
21 {
22 base (Config.SCHEMA + ".mask-corners");
23 }
24 }
25}

Subscribers

People subscribed via source and target branches