blur_effect.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. import GLib from 'gi://GLib';
  2. import GObject from 'gi://GObject';
  3. import Clutter from 'gi://Clutter';
  4. import Shell from 'gi://Shell';
  5. const SHADER_PATH = GLib.filename_from_uri(GLib.uri_resolve_relative(import.meta.url, 'blur_effect.glsl', GLib.UriFlags.NONE))[0];
  6. const get_shader_source = _ => {
  7. try {
  8. return Shell.get_file_contents_utf8_sync(SHADER_PATH);
  9. } catch (e) {
  10. console.warn(`[Blur my Shell] error loading shader from ${SHADER_PATH}: ${e}`);
  11. return null;
  12. }
  13. };
  14. export const BlurEffect = new GObject.registerClass({
  15. GTypeName: "BlurEffect",
  16. Properties: {
  17. 'radius': GObject.ParamSpec.double(
  18. `radius`,
  19. `Radius`,
  20. `Blur radius`,
  21. GObject.ParamFlags.READWRITE,
  22. 0.0, 2000.0,
  23. 200.0,
  24. ),
  25. 'brightness': GObject.ParamSpec.double(
  26. `brightness`,
  27. `Brightness`,
  28. `Blur brightness`,
  29. GObject.ParamFlags.READWRITE,
  30. 0.0, 1.0,
  31. 0.6,
  32. ),
  33. 'width': GObject.ParamSpec.double(
  34. `width`,
  35. `Width`,
  36. `Width`,
  37. GObject.ParamFlags.READWRITE,
  38. 0.0, Number.MAX_SAFE_INTEGER,
  39. 0.0,
  40. ),
  41. 'height': GObject.ParamSpec.double(
  42. `height`,
  43. `Height`,
  44. `Height`,
  45. GObject.ParamFlags.READWRITE,
  46. 0.0, Number.MAX_SAFE_INTEGER,
  47. 0.0,
  48. ),
  49. 'corner_radius': GObject.ParamSpec.double(
  50. `corner_radius`,
  51. `Corner Radius`,
  52. `Corner Radius`,
  53. GObject.ParamFlags.READWRITE,
  54. 0, Number.MAX_SAFE_INTEGER,
  55. 0,
  56. ),
  57. 'direction': GObject.ParamSpec.int(
  58. `direction`,
  59. `Direction`,
  60. `Direction`,
  61. GObject.ParamFlags.READWRITE,
  62. 0, 1,
  63. 0,
  64. ),
  65. 'chained_effect': GObject.ParamSpec.object(
  66. `chained_effect`,
  67. `Chained Effect`,
  68. `Chained Effect`,
  69. GObject.ParamFlags.READABLE,
  70. GObject.Object,
  71. ),
  72. }
  73. }, class BlurEffect extends Clutter.ShaderEffect {
  74. constructor(params, settings) {
  75. super(params);
  76. this._sigma = null;
  77. this._brightness = null;
  78. this._width = null;
  79. this._height = null;
  80. this._corner_radius = null;
  81. this._static = true;
  82. this._settings = settings;
  83. this._direction = 0;
  84. this._chained_effect = null;
  85. if (params.sigma)
  86. this.sigma = params.sigma;
  87. if (params.brightness)
  88. this.brightness = params.brightness;
  89. if (params.width)
  90. this.width = params.width;
  91. if (params.height)
  92. this.height = params.height;
  93. if (params.corner_radius)
  94. this.corner_radius = params.corner_radius;
  95. if (params.direction)
  96. this.direction = params.direction;
  97. // set shader source
  98. this._source = get_shader_source();
  99. if (this._source)
  100. this.set_shader_source(this._source);
  101. }
  102. get radius() {
  103. return this._radius;
  104. }
  105. set radius(value) {
  106. if (this._radius !== value) {
  107. this._radius = value;
  108. // like Clutter, we use the assumption radius = 2*sigma
  109. this.set_uniform_value('sigma', parseFloat(this._radius / 2 - 1e-6));
  110. if (this._chained_effect) {
  111. this._chained_effect.radius = value;
  112. }
  113. }
  114. }
  115. get brightness() {
  116. return this._brightness;
  117. }
  118. set brightness(value) {
  119. if (this._brightness !== value) {
  120. this._brightness = value;
  121. this.set_uniform_value('brightness', parseFloat(this._brightness - 1e-6));
  122. if (this._chained_effect) {
  123. this._chained_effect.brightness = value;
  124. }
  125. }
  126. }
  127. get width() {
  128. return this._width;
  129. }
  130. set width(value) {
  131. if (this._width !== value) {
  132. this._width = value;
  133. this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6));
  134. if (this._chained_effect) {
  135. this._chained_effect.width = value;
  136. }
  137. }
  138. }
  139. get height() {
  140. return this._height;
  141. }
  142. set height(value) {
  143. if (this._height !== value) {
  144. this._height = value;
  145. this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6));
  146. if (this._chained_effect) {
  147. this._chained_effect.height = value;
  148. }
  149. }
  150. }
  151. get corner_radius() {
  152. return this._corner_radius;
  153. }
  154. set corner_radius(value) {
  155. if (this._corner_radius !== value) {
  156. this._corner_radius = value;
  157. this.set_uniform_value('corner_radius', parseFloat(this._corner_radius - 1e-6));
  158. if (this._chained_effect) {
  159. this._chained_effect.corner_radius = value;
  160. }
  161. }
  162. }
  163. get direction() {
  164. return this._direction;
  165. }
  166. set direction(value) {
  167. if (this._direction !== value) {
  168. this._direction = value;
  169. }
  170. }
  171. get chained_effect() {
  172. return this._chained_effect;
  173. }
  174. vfunc_set_actor(actor) {
  175. super.vfunc_set_actor(actor);
  176. if (this._direction == 0) {
  177. this._chained_effect = new BlurEffect({
  178. radius: this.radius,
  179. brightness: this.brightness,
  180. width: this.width,
  181. height: this.height,
  182. corner_radius: this.corner_radius,
  183. direction: 1
  184. });
  185. if (actor !== null)
  186. actor.add_effect(this._chained_effect);
  187. }
  188. }
  189. vfunc_paint_target(paint_node = null, paint_context = null) {
  190. this.set_uniform_value("tex", 0);
  191. this.set_uniform_value("dir", this._direction);
  192. if (paint_node && paint_context)
  193. super.vfunc_paint_target(paint_node, paint_context);
  194. else if (paint_node)
  195. super.vfunc_paint_target(paint_node);
  196. else
  197. super.vfunc_paint_target();
  198. }
  199. });