services.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import Gio from 'gi://Gio';
  2. import GLib from 'gi://GLib';
  3. import * as Main from 'resource:///org/gnome/shell/ui/main.js';
  4. import * as LookingGlass from 'resource:///org/gnome/shell/ui/lookingGlass.js';
  5. export const ApplicationsService = class ApplicationsService {
  6. constructor() {
  7. let decoder = new TextDecoder();
  8. let path = GLib.filename_from_uri(GLib.uri_resolve_relative(
  9. import.meta.url, 'iface.xml', GLib.UriFlags.NONE)
  10. )[0];
  11. let [, buffer] = GLib.file_get_contents(path);
  12. let iface = decoder.decode(buffer);
  13. GLib.free(buffer);
  14. this.DBusImpl = Gio.DBusExportedObject.wrapJSObject(iface, this);
  15. }
  16. /// Pick Window for Preferences Page, exported to DBus client.
  17. pick() {
  18. // emit `picking` signal to know we are listening
  19. const send_picking_signal = _ =>
  20. this.DBusImpl.emit_signal(
  21. 'picking',
  22. null
  23. );
  24. // emit `picked` signal to send wm_class
  25. const send_picked_signal = wm_class =>
  26. this.DBusImpl.emit_signal(
  27. 'picked',
  28. new GLib.Variant('(s)', [wm_class])
  29. );
  30. // notify the preferences that we are listening
  31. send_picking_signal();
  32. // A very interesting way to pick a window:
  33. // 1. Open LookingGlass to mask all event handles of window
  34. // 2. Use inspector to pick window, thats is also lookingGlass do
  35. // 3. Close LookingGlass when done
  36. // It will restore event handles of window
  37. // open then hide LookingGlass
  38. const looking_class = Main.createLookingGlass();
  39. looking_class.open();
  40. looking_class.hide();
  41. // inspect window now
  42. const inspector = new LookingGlass.Inspector(Main.createLookingGlass());
  43. inspector.connect('target', (me, target, x, y) => {
  44. // remove border effect when window is picked.
  45. const effect_name = 'lookingGlass_RedBorderEffect';
  46. target
  47. .get_effects()
  48. .filter(e => e.toString().includes(effect_name))
  49. .forEach(e => target.remove_effect(e));
  50. // get wm_class_instance property of window, then pass it to DBus
  51. // client
  52. const type_str = target.toString();
  53. let actor = target;
  54. if (type_str.includes('MetaSurfaceActor'))
  55. actor = target.get_parent();
  56. if (!actor.toString().includes('WindowActor'))
  57. actor = actor.get_parent();
  58. if (!actor.toString().includes('WindowActor'))
  59. return send_picked_signal('window-not-found');
  60. send_picked_signal(
  61. actor.meta_window.get_wm_class() ?? 'window-not-found'
  62. );
  63. });
  64. // close LookingGlass when we're done
  65. inspector.connect('closed', _ => looking_class.close());
  66. }
  67. export() {
  68. this.DBusImpl.export(
  69. Gio.DBus.session,
  70. '/dev/aunetx/BlurMyShell'
  71. );
  72. };
  73. unexport() {
  74. this.DBusImpl.unexport();
  75. }
  76. };