window_row.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import Adw from 'gi://Adw';
  2. import GLib from 'gi://GLib';
  3. import GObject from 'gi://GObject';
  4. import Gio from 'gi://Gio';
  5. import Gtk from 'gi://Gtk';
  6. import { pick, on_picking, on_picked } from '../dbus/client.js';
  7. export const WindowRow = GObject.registerClass({
  8. GTypeName: 'WindowRow',
  9. Template: GLib.uri_resolve_relative(import.meta.url, '../ui/window-row.ui', GLib.UriFlags.NONE),
  10. InternalChildren: [
  11. 'window_picker',
  12. 'window_class',
  13. 'picking_failure_toast'
  14. ],
  15. }, class WindowRow extends Adw.ExpanderRow {
  16. constructor(list, app_page, app_name) {
  17. super({});
  18. this._list = list;
  19. this._app_page = app_page;
  20. // add a 'remove' button before the text
  21. let action_row = this.child.get_first_child().get_first_child();
  22. let remove_button = new Gtk.Button({
  23. 'icon-name': 'remove-window-symbolic',
  24. 'width-request': 38,
  25. 'height-request': 38,
  26. 'margin-top': 6,
  27. 'margin-bottom': 6,
  28. });
  29. remove_button.add_css_class('circular');
  30. remove_button.add_css_class('flat');
  31. action_row.add_prefix(remove_button);
  32. // connect the button to the whitelist / blacklist removal
  33. remove_button.connect('clicked', _ => this._remove_row());
  34. // bind row title to text buffer
  35. this._window_class.buffer.bind_property(
  36. 'text', this, 'title',
  37. Gio.SettingsBindFlags.BIDIRECTIONNAL
  38. );
  39. // set application name if it exists, or open the revealer and pick one
  40. if (app_name)
  41. this._window_class.buffer.text = app_name;
  42. else {
  43. app_page.close_all_expanded_rows();
  44. this.set_expanded(true);
  45. this._do_pick_window(true);
  46. }
  47. // pick a window when the picker button is clicked
  48. this._window_picker.connect('clicked', _ => this._do_pick_window());
  49. // update list on text buffer change
  50. this._window_class.connect('changed',
  51. _ => this._update_rows_titles()
  52. );
  53. }
  54. _remove_row() {
  55. this._app_page["remove_from_" + this._list](this);
  56. }
  57. _update_rows_titles() {
  58. this._app_page["update_" + this._list + "_titles"](this);
  59. }
  60. _do_pick_window(remove_if_failed = false) {
  61. // a mechanism to know if the extension is listening correcly
  62. let has_responded = false;
  63. let should_take_answer = true;
  64. setTimeout(_ => {
  65. if (!has_responded) {
  66. // show toast about failure
  67. this._app_page._preferences_window.add_toast(
  68. this._picking_failure_toast
  69. );
  70. // prevent title from changing with later picks
  71. should_take_answer = false;
  72. // remove row if asked
  73. if (remove_if_failed)
  74. this._remove_row();
  75. }
  76. }, 15);
  77. on_picking(_ =>
  78. has_responded = true
  79. );
  80. on_picked(wm_class => {
  81. if (should_take_answer) {
  82. if (wm_class == 'window-not-found') {
  83. console.warn("Can't pick window from here");
  84. return;
  85. }
  86. this._window_class.buffer.text = wm_class;
  87. }
  88. });
  89. pick();
  90. }
  91. });