Fix remaining problem in updated patch
Raphaƫl Hertzog
6 years ago
4 | 4 | |
5 | 5 | --- a/extensions/apps-menu/extension.js |
6 | 6 | +++ b/extensions/apps-menu/extension.js |
7 | @@ -114,7 +114,7 @@ class ApplicationMenuItem extends PopupM | |
7 | @@ -114,29 +114,33 @@ class ApplicationMenuItem extends PopupM | |
8 | 8 | } |
9 | 9 | }; |
10 | 10 | |
11 | 11 | -class CategoryMenuItem extends PopupMenu.PopupBaseMenuItem { |
12 | - constructor(button, category) { | |
13 | - super(); | |
14 | - this._category = category; | |
15 | - this._button = button; | |
16 | - | |
17 | - this._oldX = -1; | |
18 | - this._oldY = -1; | |
12 | 19 | +class CategoryMenuItem extends PopupMenu.PopupMenuItem { |
13 | constructor(button, category) { | |
14 | super(); | |
15 | this._category = category; | |
16 | @@ -129,8 +129,121 @@ class CategoryMenuItem extends PopupMenu | |
20 | + /* Kali patch note: the use of PopupMenuItem instead of | |
21 | + * PopupBaseMenuItem means that all the code in _onMotionEvent and | |
22 | + * isNavigatingSubmenu is no longer used. And the menu name needs to | |
23 | + * be passed to the parent constructor instead of being added in the | |
24 | + * menu item by ourselves. The _oldX/_oldY variables are not | |
25 | + * initialized as they are only needed for isNavigatingSubmenu */ | |
26 | ||
27 | + constructor(button, category) { | |
28 | let name; | |
29 | - if (this._category) | |
30 | - name = this._category.get_name(); | |
31 | + if (category) | |
32 | + name = category.get_name(); | |
17 | 33 | else |
18 | 34 | name = _("Favorites"); |
19 | 35 | |
20 | 36 | - this.actor.add_child(new St.Label({ text: name })); |
21 | 37 | - this.actor.connect('motion-event', this._onMotionEvent.bind(this)); |
22 | + this._init(name); | |
23 | + | |
24 | + //this.actor.connect('motion-event', Lang.bind(this, this._onMotionEvent)); | |
25 | + } | |
26 | + | |
27 | + activate(event) { | |
28 | + this._button.selectCategory(this._category, this); | |
38 | + super(name); | |
39 | + | |
40 | + this._category = category; | |
41 | + this._button = button; | |
42 | } | |
43 | ||
44 | activate(event) { | |
45 | this._button.selectCategory(this._category, this); | |
46 | - this._button.scrollToCatButton(this); | |
47 | - super.activate(event); | |
29 | 48 | + //this._button.scrollToCatButton(this); |
30 | 49 | + // we don't chain up here so that clicking on a category doesn't |
31 | 50 | + // close the menu |
32 | + } | |
33 | + | |
34 | + _isNavigatingSubmenu([x, y]) { | |
35 | + let [posX, posY] = this.actor.get_transformed_position(); | |
36 | + | |
37 | + if (this._oldX == -1) { | |
38 | + this._oldX = x; | |
39 | + this._oldY = y; | |
40 | + return true; | |
41 | + } | |
42 | + | |
43 | + let deltaX = Math.abs(x - this._oldX); | |
44 | + let deltaY = Math.abs(y - this._oldY); | |
45 | + | |
46 | + this._oldX = x; | |
47 | + this._oldY = y; | |
48 | + | |
49 | + // If it lies outside the x-coordinates then it is definitely outside. | |
50 | + if (posX > x || posX + this.actor.width < x) | |
51 | + return false; | |
52 | + | |
53 | + // If it lies inside the menu item then it is definitely inside. | |
54 | + if (posY <= y && posY + this.actor.height >= y) | |
55 | + return true; | |
56 | + | |
57 | + // We want the keep-up triangle only if the movement is more | |
58 | + // horizontal than vertical. | |
59 | + if (deltaX * HORIZ_FACTOR < deltaY) | |
60 | + return false; | |
61 | + | |
62 | + // Check whether the point lies inside triangle ABC, and a similar | |
63 | + // triangle on the other side of the menu item. | |
64 | + // | |
65 | + // +---------------------+ | |
66 | + // | menu item | | |
67 | + // A +---------------------+ C | |
68 | + // P | | |
69 | + // B | |
70 | + | |
71 | + // Ensure that the point P always lies below line AC so that we can | |
72 | + // only check for triangle ABC. | |
73 | + if (posY > y) { | |
74 | + let offset = posY - y; | |
75 | + y = posY + this.actor.height + offset; | |
76 | + } | |
77 | + | |
78 | + // Ensure that A is (0, 0). | |
79 | + x -= posX; | |
80 | + y -= posY + this.actor.height; | |
81 | + | |
82 | + // Check which side of line AB the point P lies on by taking the | |
83 | + // cross-product of AB and AP. See: | |
84 | + // http://stackoverflow.com/questions/3461453/determine-which-side-of-a-line-a-point-lies | |
85 | + if (((this.actor.width * y) - (NAVIGATION_REGION_OVERSHOOT * x)) <= 0) | |
86 | + return true; | |
87 | + | |
88 | + return false; | |
89 | + } | |
90 | + | |
91 | + _onMotionEvent(actor, event) { | |
92 | + if (!Clutter.get_pointer_grab()) { | |
93 | + this._oldX = -1; | |
94 | + this._oldY = -1; | |
95 | + Clutter.grab_pointer(this.actor); | |
96 | + } | |
97 | + this.actor.hover = true; | |
98 | + | |
99 | + if (this._isNavigatingSubmenu(event.get_coords())) | |
100 | + return true; | |
101 | + | |
102 | + this._oldX = -1; | |
103 | + this._oldY = -1; | |
104 | + this.actor.hover = false; | |
105 | + Clutter.ungrab_pointer(); | |
106 | + return false; | |
107 | + } | |
108 | + | |
109 | + setActive(active, params) { | |
110 | + if (active) { | |
111 | + this._button.selectCategory(this._category, this); | |
112 | + //this._button.scrollToCatButton(this); | |
113 | + } | |
114 | + super.setActive(active, params); | |
115 | + } | |
116 | +}; | |
117 | + | |
118 | +class ParentCategoryMenuItem extends PopupMenu.PopupSubMenuMenuItem { | |
119 | + constructor(text, wantIcon, button, category) { | |
120 | + super(text, wantIcon); | |
121 | + this._category = category; | |
122 | + this._button = button; | |
123 | + | |
124 | + this._oldX = -1; | |
125 | + this._oldY = -1; | |
126 | + | |
127 | + let name; | |
128 | + if (this._category) | |
129 | + name = this._category.get_name(); | |
130 | + else | |
131 | + name = _("Favorites"); | |
132 | + | |
133 | + this._init(name, false); | |
134 | + | |
135 | + //this.actor.connect('motion-event', Lang.bind(this, this._onMotionEvent)); | |
136 | + | |
137 | } | |
138 | ||
139 | activate(event) { | |
140 | @@ -222,12 +335,26 @@ class CategoryMenuItem extends PopupMenu | |
51 | + //super.activate(event); | |
52 | } | |
53 | ||
54 | _isNavigatingSubmenu([x, y]) { | |
55 | @@ -222,12 +226,55 @@ class CategoryMenuItem extends PopupMenu | |
141 | 56 | setActive(active, params) { |
142 | 57 | if (active) { |
143 | 58 | this._button.selectCategory(this._category, this); |
148 | 63 | } |
149 | 64 | }; |
150 | 65 | |
66 | +class ParentCategoryMenuItem extends PopupMenu.PopupSubMenuMenuItem { | |
67 | + constructor(button, category) { | |
68 | + let name; | |
69 | + if (category) | |
70 | + name = category.get_name(); | |
71 | + else | |
72 | + name = _("Favorites"); | |
73 | + | |
74 | + super(name, false); | |
75 | + | |
76 | + this._category = category; | |
77 | + this._button = button; | |
78 | + } | |
79 | + | |
80 | + activate(event) { | |
81 | + this._button.selectCategory(this._category, this); | |
82 | + this._button.scrollToCatButton(this); | |
83 | + super.activate(event); | |
84 | + } | |
85 | + | |
86 | + setActive(active, params) { | |
87 | + if (active) { | |
88 | + this._button.selectCategory(this._category, this); | |
89 | + //this._button.scrollToCatButton(this); | |
90 | + } | |
91 | + super.setActive(active, params); | |
92 | + } | |
93 | +}; | |
94 | + | |
151 | 95 | +class PopupMenuScrollView extends PopupMenu.PopupMenuSection { |
152 | 96 | + constructor() { |
153 | 97 | + super(); |
165 | 109 | class ApplicationsMenu extends PopupMenu.PopupMenu { |
166 | 110 | constructor(sourceActor, arrowAlignment, arrowSide, button) { |
167 | 111 | super(sourceActor, arrowAlignment, arrowSide); |
168 | @@ -462,7 +589,7 @@ class ApplicationsButton extends PanelMe | |
112 | @@ -462,7 +509,7 @@ class ApplicationsButton extends PanelMe | |
169 | 113 | _onTreeChanged() { |
170 | 114 | if (this.menu.isOpen) { |
171 | 115 | this._redisplay(); |
174 | 118 | } else { |
175 | 119 | this.reloadFlag = true; |
176 | 120 | } |
177 | @@ -536,7 +663,8 @@ class ApplicationsButton extends PanelMe | |
121 | @@ -536,7 +583,7 @@ class ApplicationsButton extends PanelMe | |
178 | 122 | this._redisplay(); |
179 | 123 | this.reloadFlag = false; |
180 | 124 | } |
181 | 125 | - this.mainBox.show(); |
182 | + //this.categoriesBox.box.width = this._menuContainerGetPreferredWidth(this.categoriesBox.box); | |
183 | 126 | + this.mainBox.actor.show(); |
184 | 127 | } |
185 | 128 | super._onOpenStateChanged(menu, open); |
186 | 129 | } |
187 | @@ -550,11 +678,11 @@ class ApplicationsButton extends PanelMe | |
130 | @@ -550,13 +597,14 @@ class ApplicationsButton extends PanelMe | |
188 | 131 | |
189 | 132 | _redisplay() { |
190 | 133 | this.applicationsBox.destroy_all_children(); |
197 | 140 | + _loadCategory(dir, parentCategory) { |
198 | 141 | let iter = dir.iter(); |
199 | 142 | let nextType; |
143 | + let categoryId = dir.get_menu_id(); | |
200 | 144 | while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) { |
201 | @@ -575,8 +703,18 @@ class ApplicationsButton extends PanelMe | |
145 | if (nextType == GMenu.TreeItemType.ENTRY) { | |
146 | let entry = iter.get_entry(); | |
147 | @@ -575,8 +623,17 @@ class ApplicationsButton extends PanelMe | |
202 | 148 | this.applicationsByCategory[categoryId].push('separator'); |
203 | 149 | } else if (nextType == GMenu.TreeItemType.DIRECTORY) { |
204 | 150 | let subdir = iter.get_directory(); |
205 | 151 | - if (!subdir.get_is_nodisplay()) |
206 | 152 | - this._loadCategory(categoryId, subdir); |
207 | 153 | + if (!subdir.get_is_nodisplay()) { |
208 | + let menu_id = subdir.get_menu_id(); | |
209 | + this.applicationsByCategory[menu_id] = []; | |
154 | + let subdirCategoryId = subdir.get_menu_id(); | |
155 | + this.applicationsByCategory[subdirCategoryId] = []; | |
210 | 156 | + let categoryMenuItem = new ParentCategoryMenuItem(this, subdir); |
211 | 157 | + this._loadCategory(subdir, categoryMenuItem); |
212 | 158 | + if (categoryMenuItem.menu.isEmpty()) |
213 | 159 | + categoryMenuItem = new CategoryMenuItem(this, subdir); |
214 | + if (this.applicationsByCategory[menu_id].length > 0 || !categoryMenuItem.menu.isEmpty()) { | |
160 | + if (this.applicationsByCategory[subdirCategoryId].length > 0 || !categoryMenuItem.menu.isEmpty()) { | |
215 | 161 | + parentCategory.menu.addMenuItem(categoryMenuItem); |
216 | + } | |
162 | + } | |
217 | 163 | + } |
218 | + | |
219 | 164 | } |
220 | 165 | } |
221 | 166 | } |
222 | @@ -597,8 +735,8 @@ class ApplicationsButton extends PanelMe | |
167 | @@ -597,8 +654,8 @@ class ApplicationsButton extends PanelMe | |
223 | 168 | } |
224 | 169 | |
225 | 170 | scrollToCatButton(button) { |
230 | 175 | let currentScrollValue = catsScrollBoxAdj.get_value(); |
231 | 176 | let boxHeight = catsScrollBoxAlloc.y2 - catsScrollBoxAlloc.y1; |
232 | 177 | let buttonAlloc = button.actor.get_allocation_box(); |
233 | @@ -612,10 +750,16 @@ class ApplicationsButton extends PanelMe | |
178 | @@ -612,10 +669,16 @@ class ApplicationsButton extends PanelMe | |
234 | 179 | } |
235 | 180 | |
236 | 181 | _createLayout() { |
249 | 194 | this.applicationsScrollBox = new St.ScrollView({ x_fill: true, y_fill: false, |
250 | 195 | y_align: St.Align.START, |
251 | 196 | style_class: 'apps-menu vfade' }); |
252 | @@ -627,44 +771,77 @@ class ApplicationsButton extends PanelMe | |
197 | @@ -627,6 +690,7 @@ class ApplicationsButton extends PanelMe | |
253 | 198 | vscroll.connect('scroll-stop', () => { |
254 | 199 | this.menu.passEvents = false; |
255 | 200 | }); |
256 | - this.categoriesScrollBox = new St.ScrollView({ x_fill: true, y_fill: false, | |
257 | - y_align: St.Align.START, | |
258 | - style_class: 'vfade' }); | |
259 | - this.categoriesScrollBox.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); | |
260 | - vscroll = this.categoriesScrollBox.get_vscroll_bar(); | |
261 | - vscroll.connect('scroll-start', () => { this.menu.passEvents = true; }); | |
262 | - vscroll.connect('scroll-stop', () => { this.menu.passEvents = false; }); | |
263 | - this.leftBox.add(this.categoriesScrollBox, { expand: true, | |
264 | - x_fill: true, y_fill: true, | |
265 | - y_align: St.Align.START }); | |
266 | +// this.categoriesScrollBox = new St.ScrollView({ x_fill: true, y_fill: false, | |
267 | +// y_align: St.Align.START, | |
268 | + // style_class: 'vfade' }); | |
269 | +// this.categoriesScrollBox.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC); | |
270 | +// vscroll = this.categoriesScrollBox.get_vscroll_bar(); | |
271 | +// vscroll.connect('scroll-start', () => { this.menu.passEvents = true; }); | |
272 | +// vscroll.connect('scroll-stop', () => { this.menu.passEvents = false; }); | |
273 | +// this.leftBox.add(this.categoriesScrollBox, { expand: true, | |
274 | +// x_fill: true, y_fill: true, | |
275 | +// y_align: St.Align.START }); | |
276 | ||
201 | +/* | |
202 | this.categoriesScrollBox = new St.ScrollView({ x_fill: true, y_fill: false, | |
203 | y_align: St.Align.START, | |
204 | style_class: 'vfade' }); | |
205 | @@ -637,14 +701,17 @@ class ApplicationsButton extends PanelMe | |
206 | this.leftBox.add(this.categoriesScrollBox, { expand: true, | |
207 | x_fill: true, y_fill: true, | |
208 | y_align: St.Align.START }); | |
209 | - | |
210 | +*/ | |
277 | 211 | let activities = new ActivitiesMenuItem(this); |
278 | - this.leftBox.add(activities.actor, { expand: false, | |
279 | - x_fill: true, y_fill: false, | |
280 | - y_align: St.Align.START }); | |
281 | +// this.leftBox.add(activities.actor, { expand: false, | |
282 | +// x_fill: true, y_fill: false, | |
283 | +// y_align: St.Align.START }); | |
212 | +/* | |
213 | this.leftBox.add(activities.actor, { expand: false, | |
214 | x_fill: true, y_fill: false, | |
215 | y_align: St.Align.START }); | |
216 | +*/ | |
284 | 217 | |
285 | 218 | this.applicationsBox = new St.BoxLayout({ vertical: true }); |
286 | 219 | this.applicationsScrollBox.add_actor(this.applicationsBox); |
287 | - this.categoriesBox = new St.BoxLayout({ vertical: true }); | |
288 | - this.categoriesScrollBox.add_actor(this.categoriesBox); | |
289 | +// this.categoriesBox = new St.BoxLayout({ vertical: true }); | |
290 | +// this.categoriesScrollBox.add_actor(this.categoriesBox); | |
291 | ||
292 | - this.mainBox.add(this.leftBox); | |
293 | - this.mainBox.add(this._createVertSeparator(), { expand: false, x_fill: false, y_fill: true}); | |
294 | - this.mainBox.add(this.applicationsScrollBox, { expand: true, x_fill: true, y_fill: true }); | |
295 | - section.actor.add_actor(this.mainBox); | |
296 | +// this.mainBox.add(this.leftBox); | |
297 | +// this.mainBox.add(this._createVertSeparator(), { expand: false, x_fill: false, y_fill: true}); | |
298 | +// this.mainBox.add(this.applicationsScrollBox, { expand: true, x_fill: true, y_fill: true }); | |
299 | +// section.actor.add_actor(this.mainBox); | |
220 | +/* | |
221 | this.categoriesBox = new St.BoxLayout({ vertical: true }); | |
222 | this.categoriesScrollBox.add_actor(this.categoriesBox); | |
223 | ||
224 | @@ -652,19 +719,39 @@ class ApplicationsButton extends PanelMe | |
225 | this.mainBox.add(this._createVertSeparator(), { expand: false, x_fill: false, y_fill: true}); | |
226 | this.mainBox.add(this.applicationsScrollBox, { expand: true, x_fill: true, y_fill: true }); | |
227 | section.actor.add_actor(this.mainBox); | |
228 | +*/ | |
300 | 229 | + this.categoriesBox = new PopupMenuScrollView(); |
301 | 230 | + vscroll = this.categoriesBox.actor.get_vscroll_bar(); |
302 | 231 | + vscroll.connect('scroll-start', () => { this.menu.passEvents = true; }); |
303 | 232 | + vscroll.connect('scroll-stop', () => { this.menu.passEvents = false; }); |
304 | 233 | + this.leftBox.addMenuItem(this.categoriesBox); |
305 | + // FIXME we re-add it to apply the right properties, but re-adding | |
306 | + // it causes a warning | |
234 | + // we re-add it to apply the right properties | |
307 | 235 | + this.leftBox.actor.add(this.categoriesBox.actor, { expand: true, |
308 | 236 | + x_fill: true, y_fill: true, |
309 | 237 | + y_align: St.Align.START }); |
317 | 245 | + this.mainBox.actor.add(this.applicationsScrollBox, { expand: true, |
318 | 246 | + x_fill: true, y_fill: true }); |
319 | 247 | + section.addMenuItem(this.mainBox); |
320 | + } | |
321 | + | |
322 | + _menuContainerGetPreferredWidth(container) { | |
323 | + let max_width = 0; | |
324 | + for (let child = container.get_first_child(); | |
325 | + child; | |
326 | + child = child.get_next_sibling()) { | |
327 | + // recurse into submenus | |
328 | + if (child._delegate instanceof ParentCategoryMenuItem) | |
329 | + max_width = Math.max(max_width, this._menuContainerGetPreferredWidth(child._delegate.menu.box)); | |
330 | + max_width = Math.max(max_width, child.width); | |
331 | + } | |
332 | + return max_width; | |
333 | 248 | } |
334 | 249 | |
335 | 250 | _display() { |
349 | 264 | let iter = root.iter(); |
350 | 265 | let nextType; |
351 | 266 | while ((nextType = iter.next()) != GMenu.TreeItemType.INVALID) { |
352 | @@ -673,10 +850,12 @@ class ApplicationsButton extends PanelMe | |
267 | @@ -673,10 +760,12 @@ class ApplicationsButton extends PanelMe | |
353 | 268 | if (!dir.get_is_nodisplay()) { |
354 | 269 | let categoryId = dir.get_menu_id(); |
355 | 270 | this.applicationsByCategory[categoryId] = []; |
366 | 281 | } |
367 | 282 | } |
368 | 283 | } |
369 | @@ -685,8 +864,9 @@ class ApplicationsButton extends PanelMe | |
284 | @@ -685,8 +774,9 @@ class ApplicationsButton extends PanelMe | |
370 | 285 | //Load applications |
371 | 286 | this._displayButtons(this._listApplications(null)); |
372 | 287 | |
378 | 293 | } |
379 | 294 | |
380 | 295 | selectCategory(dir, categoryMenuItem) { |
296 | @@ -701,6 +791,21 @@ class ApplicationsButton extends PanelMe | |
297 | this._displayButtons(this._listApplications(dir.get_menu_id())); | |
298 | else | |
299 | this._displayButtons(this._listApplications(null)); | |
300 | + | |
301 | + if (categoryMenuItem) | |
302 | + this.updateOrnament(this.categoriesBox, categoryMenuItem); | |
303 | + } | |
304 | + | |
305 | + updateOrnament(menu_item, category_menu_item) { | |
306 | + menu_item._getMenuItems().forEach(sub_menu_item => { | |
307 | + if (sub_menu_item.menu != undefined) | |
308 | + this.updateOrnament(sub_menu_item.menu, category_menu_item); | |
309 | + if (sub_menu_item == category_menu_item) { | |
310 | + sub_menu_item.setOrnament(PopupMenu.Ornament.CHECK); | |
311 | + } else { | |
312 | + sub_menu_item.setOrnament(PopupMenu.Ornament.NONE); | |
313 | + } | |
314 | + }, this); | |
315 | } | |
316 | ||
317 | _displayButtons(apps) { |