Skip to content

Instantly share code, notes, and snippets.

@itzexor
Last active August 23, 2019 05:16
Show Gist options
  • Save itzexor/98cf5b3af6b884a76b5311e1dbefc1fe to your computer and use it in GitHub Desktop.
Save itzexor/98cf5b3af6b884a76b5311e1dbefc1fe to your computer and use it in GitHub Desktop.
diff --git a/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js b/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js
index b97955d8..81b2e43a 100644
--- a/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js
+++ b/files/usr/share/cinnamon/applets/menu@cinnamon.org/applet.js
@@ -11,6 +11,7 @@ const AppFavorites = imports.ui.appFavorites;
const Gtk = imports.gi.Gtk;
const Atk = imports.gi.Atk;
const Gio = imports.gi.Gio;
+const GObject = imports.gi.GObject;
const GnomeSession = imports.misc.gnomeSession;
const ScreenSaver = imports.misc.screenSaver;
const FileUtils = imports.misc.fileUtils;
@@ -59,6 +60,85 @@ const RefreshFlags = Object.freeze({
});
const REFRESH_ALL_MASK = 0b11111;
+const VectorBox = GObject.registerClass(
+class VectorBox extends St.Polygon {
+ _init(...args) {
+ super._init(...args);
+ this.show_on_set_parent = false;
+ this.reactive = true;
+ this.debug = true;
+
+ this._parent = null;
+ this._updateEnabled = true;
+ }
+
+ vfunc_parent_set(oldParent) {
+ // can't access `parent` directly
+ this._parent = this.get_parent();
+ }
+
+ vfunc_motion_event(event) {
+ return this.maybeUpdate();
+ }
+
+ vfunc_leave_event(event) {
+ this.hide();
+ return true;
+ }
+
+ _update() {
+ if (!this._updateEnabled || !this.visible || !this._parent)
+ return false;
+
+ let [mx, my, ] = global.get_pointer();
+ let [x, y] = this.get_transformed_position();
+ x = mx - x;
+ y = my - y;
+
+ if (x < 0 || x > this.width || y < 0 || y > this.height) {
+ this.hide();
+ return false;
+ }
+
+ this.ulc_x = x;
+ this.ulc_y = y;
+ this.llc_x = x;
+ this.llc_y = y;
+ this.queue_relayout();
+ return true;
+ }
+
+ show() {
+ if (!this._parent)
+ return;
+
+ if (!this.visible) {
+ this.set_size(...this._parent.get_size());
+ this.urc_x = this._parent.width;
+ this.urc_y = 0;
+ this.lrc_x = this._parent.width;
+ this.lrc_y = this._parent.height;
+
+ super.show();
+ }
+
+ this.maybeUpdate(25);
+ }
+
+ hide() {
+ super.hide();
+ this._updateEnabled = true;
+ }
+
+ maybeUpdate(delay=350) {
+ if (!this._update())
+ return false;
+ this._updateEnabled = false;
+ Mainloop.timeout_add(delay, () => { this._updateEnabled = true });
+ return true;
+ }
+});
+
/* VisibleChildIterator takes a container (boxlayout, etc.)
* and creates an array of its visible children and their index
* positions. We can then work through that list without
@@ -1234,7 +1314,7 @@ class CinnamonMenuApplet extends Applet.TextIconApplet {
this._clearAllSelections(true);
this._scrollToButton(null, this.favoritesScrollBox);
- this.destroyVectorBox();
+ this.vectorBox.hide();
}
}
@@ -1909,7 +1989,7 @@ class CinnamonMenuApplet extends Applet.TextIconApplet {
button.isHovered = true;
this._clearPrevCatSelection(button.actor);
this._select_category(button.categoryId);
- this.makeVectorBox(button.actor);
+ this.vectorBox.show();
} else {
this._previousVisibleIndex = parent._vis_iter.getVisibleIndex(button.actor);
@@ -1981,109 +2061,6 @@ class CinnamonMenuApplet extends Applet.TextIconApplet {
}
}
- /*
- * The vectorBox overlays the the categoriesBox to aid in navigation from categories to apps
- * by preventing misselections. It is set to the same size as the categoriesOverlayBox and
- * categoriesBox.
- *
- * The actor is a quadrilateral that we turn into a triangle by setting the A and B vertices to
- * the same position. The size and origin of the vectorBox are calculated in _getVectorInfo().
- * Using those properties, the bounding box is sized as (w, h) and the triangle is defined as
- * follows:
- * _____
- * | /|D
- * | / | AB: (mx, my)
- * | A/ | C: (w, h)
- * | B\ | D: (w, 0)
- * | \ |
- * |____\|C
- */
-
- _getVectorInfo() {
- let [mx, my, mask] = global.get_pointer();
- let [bx, by] = this.categoriesOverlayBox.get_transformed_position();
- let [bw, bh] = this.categoriesOverlayBox.get_transformed_size();
-
- let xformed_mx = mx - bx;
- let xformed_my = my - by;
-
- if (xformed_mx < 0 || xformed_mx > bw || xformed_my < 0 || xformed_my > bh) {
- return null;
- }
-
- return { mx: xformed_mx,
- my: xformed_my,
- w: this.categoriesOverlayBox.width,
- h: this.categoriesOverlayBox.height };
- }
-
- makeVectorBox(actor) {
- this.destroyVectorBox(actor);
- let vi = this._getVectorInfo();
- if (!vi)
- return;
-
- if (this.vectorBox) {
- this.vectorBox.visible = true;
- } else {
- this.vectorBox = new St.Polygon({ debug: false, reactive: true });
-
- this.categoriesOverlayBox.add_actor(this.vectorBox);
-
- this.vectorBox.connect("leave-event", Lang.bind(this, this.destroyVectorBox));
- this.vectorBox.connect("motion-event", Lang.bind(this, this.maybeUpdateVectorBox));
- }
-
- Object.assign(this.vectorBox, { width: vi.w, height: vi.h,
- ulc_x: vi.mx, ulc_y: vi.my,
- llc_x: vi.mx, llc_y: vi.my,
- urc_x: vi.w, urc_y: 0,
- lrc_x: vi.w, lrc_y: vi.h });
-
- this.actor_motion_id = actor.connect("motion-event", Lang.bind(this, this.maybeUpdateVectorBox));
- this.current_motion_actor = actor;
- }
-
- maybeUpdateVectorBox() {
- if (this.vector_update_loop) {
- Mainloop.source_remove(this.vector_update_loop);
- this.vector_update_loop = 0;
- }
- this.vector_update_loop = Mainloop.timeout_add(50, Lang.bind(this, this.updateVectorBox));
- }
-
- updateVectorBox(actor) {
- if (!this.current_motion_actor)
- return;
- let vi = this._getVectorInfo();
- if (vi) {
- this.vectorBox.ulc_x = vi.mx;
- this.vectorBox.llc_x = vi.mx;
- this.vectorBox.queue_repaint();
- } else {
- this.destroyVectorBox(actor);
- }
- this.vector_update_loop = 0;
- return false;
- }
-
- destroyVectorBox(actor) {
- if (!this.vectorBox)
- return;
-
- if (this.vector_update_loop) {
- Mainloop.source_remove(this.vector_update_loop);
- this.vector_update_loop = 0;
- }
-
- if (this.actor_motion_id > 0 && this.current_motion_actor != null) {
- this.current_motion_actor.disconnect(this.actor_motion_id);
- this.actor_motion_id = 0;
- this.current_motion_actor = null;
- this.vectorBox.visible = false;
- }
- }
-
_refreshPlaces () {
for (let i = 0; i < this._placesButtons.length; i ++) {
this._placesButtons[i].actor.destroy();
@@ -2349,7 +2326,6 @@ class CinnamonMenuApplet extends Applet.TextIconApplet {
_display() {
this._activeContainer = null;
this._activeActor = null;
- this.vectorBox = null;
this.actor_motion_id = 0;
this.vector_update_loop = null;
this.current_motion_actor = null;
@@ -2391,6 +2367,8 @@ class CinnamonMenuApplet extends Applet.TextIconApplet {
vertical: true,
accessible_role: Atk.Role.LIST });
this.categoriesOverlayBox.add_actor(this.categoriesBox);
+ this.vectorBox = new VectorBox();
+ this.categoriesOverlayBox.add_actor(this.vectorBox);
this.applicationsScrollBox = new St.ScrollView({ x_fill: true, y_fill: false, y_align: St.Align.START, style_class: 'vfade menu-applications-scrollbox' });
this.favoritesScrollBox = new St.ScrollView({
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment