1+ import Shell from 'gi://Shell' ;
2+ import Clutter from 'gi://Clutter' ;
3+ import * as Main from 'resource:///org/gnome/shell/ui/main.js' ;
4+
5+ import { PaintSignals } from '../effects/paint_signals.js' ;
6+ const Tweener = imports . tweener . tweener ;
7+
8+ const transparent = Clutter . Color . from_pixel ( 0x00000000 ) ;
9+ const FOLDER_DIALOG_ANIMATION_TIME = 200 ;
10+
11+ const DIALOGS_STYLES = [
12+ "appfolder-dialogs-transparent" ,
13+ "appfolder-dialogs-light" ,
14+ "appfolder-dialogs-dark"
15+ ] ;
16+
17+ let original_zoomAndFadeIn = null ;
18+ let original_zoomAndFadeOut = null ;
19+ let sigma ;
20+ let brightness ;
21+
22+ let _zoomAndFadeIn = function ( ) {
23+ let [ sourceX , sourceY ] =
24+ this . _source . get_transformed_position ( ) ;
25+ let [ dialogX , dialogY ] =
26+ this . child . get_transformed_position ( ) ;
27+
28+ this . child . set ( {
29+ translation_x : sourceX - dialogX ,
30+ translation_y : sourceY - dialogY ,
31+ scale_x : this . _source . width / this . child . width ,
32+ scale_y : this . _source . height / this . child . height ,
33+ opacity : 0 ,
34+ } ) ;
35+
36+ this . set_background_color ( transparent ) ;
37+
38+ let blur_effect = this . get_effect ( "appfolder-blur" ) ;
39+
40+ blur_effect . sigma = 0 ;
41+ blur_effect . brightness = 1.0 ;
42+ Tweener . addTween ( blur_effect ,
43+ {
44+ sigma : sigma ,
45+ brightness : brightness ,
46+ time : FOLDER_DIALOG_ANIMATION_TIME / 1000 ,
47+ transition : 'easeOutQuad'
48+ }
49+ ) ;
50+
51+ this . child . ease ( {
52+ translation_x : 0 ,
53+ translation_y : 0 ,
54+ scale_x : 1 ,
55+ scale_y : 1 ,
56+ opacity : 255 ,
57+ duration : FOLDER_DIALOG_ANIMATION_TIME ,
58+ mode : Clutter . AnimationMode . EASE_OUT_QUAD ,
59+ } ) ;
60+
61+ this . _needsZoomAndFade = false ;
62+
63+ if ( this . _sourceMappedId === 0 ) {
64+ this . _sourceMappedId = this . _source . connect (
65+ 'notify::mapped' , this . _zoomAndFadeOut . bind ( this ) ) ;
66+ }
67+ } ;
68+
69+ let _zoomAndFadeOut = function ( ) {
70+ if ( ! this . _isOpen )
71+ return ;
72+
73+ if ( ! this . _source . mapped ) {
74+ this . hide ( ) ;
75+ return ;
76+ }
77+
78+ let [ sourceX , sourceY ] =
79+ this . _source . get_transformed_position ( ) ;
80+ let [ dialogX , dialogY ] =
81+ this . child . get_transformed_position ( ) ;
82+
83+ this . set_background_color ( transparent ) ;
84+
85+ let blur_effect = this . get_effect ( "appfolder-blur" ) ;
86+ Tweener . addTween ( blur_effect ,
87+ {
88+ sigma : 0 ,
89+ brightness : 1.0 ,
90+ time : FOLDER_DIALOG_ANIMATION_TIME / 1000 ,
91+ transition : 'easeInQuad'
92+ }
93+ ) ;
94+
95+ this . child . ease ( {
96+ translation_x : sourceX - dialogX ,
97+ translation_y : sourceY - dialogY ,
98+ scale_x : this . _source . width / this . child . width ,
99+ scale_y : this . _source . height / this . child . height ,
100+ opacity : 0 ,
101+ duration : FOLDER_DIALOG_ANIMATION_TIME ,
102+ mode : Clutter . AnimationMode . EASE_OUT_QUAD ,
103+ onComplete : ( ) => {
104+ this . child . set ( {
105+ translation_x : 0 ,
106+ translation_y : 0 ,
107+ scale_x : 1 ,
108+ scale_y : 1 ,
109+ opacity : 255 ,
110+ } ) ;
111+ this . hide ( ) ;
112+
113+ this . _popdownCallbacks . forEach ( func => func ( ) ) ;
114+ this . _popdownCallbacks = [ ] ;
115+ } ,
116+ } ) ;
117+
118+ this . _needsZoomAndFade = false ;
119+ } ;
120+
121+
122+ export const AppFoldersBlur = class AppFoldersBlur {
123+ constructor ( connections , settings , _ ) {
124+ this . connections = connections ;
125+ this . paint_signals = new PaintSignals ( connections ) ;
126+ this . settings = settings ;
127+ }
128+
129+ enable ( ) {
130+ this . _log ( "blurring appfolders" ) ;
131+
132+ brightness = this . settings . appfolder . CUSTOMIZE
133+ ? this . settings . appfolder . BRIGHTNESS
134+ : this . settings . BRIGHTNESS ;
135+ sigma = this . settings . appfolder . CUSTOMIZE
136+ ? this . settings . appfolder . SIGMA
137+ : this . settings . SIGMA ;
138+
139+ let appDisplay = Main . overview . _overview . controls . _appDisplay ;
140+
141+ if ( appDisplay . _folderIcons . length > 0 ) {
142+ this . blur_appfolders ( ) ;
143+ }
144+
145+ this . connections . connect (
146+ appDisplay , 'view-loaded' , this . blur_appfolders . bind ( this )
147+ ) ;
148+ }
149+
150+ blur_appfolders ( ) {
151+ let appDisplay = Main . overview . _overview . controls . _appDisplay ;
152+
153+ if ( this . settings . HACKS_LEVEL === 1 || this . settings . HACKS_LEVEL === 2 )
154+ this . _log ( `appfolders hack level ${ this . settings . HACKS_LEVEL } ` ) ;
155+
156+ appDisplay . _folderIcons . forEach ( icon => {
157+ icon . _ensureFolderDialog ( ) ;
158+
159+ if ( original_zoomAndFadeIn == null ) {
160+ original_zoomAndFadeIn = icon . _dialog . _zoomAndFadeIn ;
161+ }
162+ if ( original_zoomAndFadeOut == null ) {
163+ original_zoomAndFadeOut = icon . _dialog . _zoomAndFadeOut ;
164+ }
165+
166+ let blur_effect = new Shell . BlurEffect ( {
167+ name : "appfolder-blur" ,
168+ sigma : sigma ,
169+ brightness : brightness ,
170+ mode : Shell . BlurMode . BACKGROUND
171+ } ) ;
172+
173+ icon . _dialog . remove_effect_by_name ( "appfolder-blur" ) ;
174+ icon . _dialog . add_effect ( blur_effect ) ;
175+
176+ DIALOGS_STYLES . forEach (
177+ style => icon . _dialog . _viewBox . remove_style_class_name ( style )
178+ ) ;
179+
180+ if ( this . settings . appfolder . STYLE_DIALOGS > 0 )
181+ icon . _dialog . _viewBox . add_style_class_name (
182+ DIALOGS_STYLES [ this . settings . appfolder . STYLE_DIALOGS - 1 ]
183+ ) ;
184+
185+ // finally override the builtin functions
186+ icon . _dialog . _zoomAndFadeIn = _zoomAndFadeIn ;
187+ icon . _dialog . _zoomAndFadeOut = _zoomAndFadeOut ;
188+
189+
190+ // HACK
191+ //
192+ //`Shell.BlurEffect` does not repaint when shadows are under it. [1]
193+ //
194+ // This does not entirely fix this bug (shadows caused by windows
195+ // still cause artifacts), but it prevents the shadows of the panel
196+ // buttons to cause artifacts on the panel itself
197+ //
198+ // [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857
199+
200+ if ( this . settings . HACKS_LEVEL === 1 || this . settings . HACKS_LEVEL === 2 ) {
201+ this . paint_signals . disconnect_all_for_actor ( icon . _dialog ) ;
202+ this . paint_signals . connect ( icon . _dialog , blur_effect ) ;
203+ } else {
204+ this . paint_signals . disconnect_all ( ) ;
205+ }
206+ } ) ;
207+ } ;
208+
209+ set_sigma ( s ) {
210+ sigma = s ;
211+ if ( this . settings . appfolder . BLUR )
212+ this . blur_appfolders ( ) ;
213+ }
214+
215+ set_brightness ( b ) {
216+ brightness = b ;
217+ if ( this . settings . appfolder . BLUR )
218+ this . blur_appfolders ( ) ;
219+ }
220+
221+ // not implemented for dynamic blur
222+ set_color ( c ) { }
223+ set_noise_amount ( n ) { }
224+ set_noise_lightness ( l ) { }
225+
226+ disable ( ) {
227+ this . _log ( "removing blur from appfolders" ) ;
228+
229+ let appDisplay = Main . overview . _overview . controls . _appDisplay ;
230+
231+ if ( original_zoomAndFadeIn != null ) {
232+ appDisplay . _folderIcons . forEach ( icon => {
233+ if ( icon . _dialog )
234+ icon . _dialog . _zoomAndFadeIn = original_zoomAndFadeIn ;
235+ } ) ;
236+ }
237+
238+ if ( original_zoomAndFadeOut != null ) {
239+ appDisplay . _folderIcons . forEach ( icon => {
240+ if ( icon . _dialog )
241+ icon . _dialog . _zoomAndFadeOut = original_zoomAndFadeOut ;
242+ } ) ;
243+ }
244+
245+ appDisplay . _folderIcons . forEach ( icon => {
246+ if ( icon . _dialog ) {
247+ icon . _dialog . remove_effect_by_name ( "appfolder-blur" ) ;
248+ DIALOGS_STYLES . forEach (
249+ s => icon . _dialog . _viewBox . remove_style_class_name ( s )
250+ ) ;
251+ }
252+ } ) ;
253+
254+ this . connections . disconnect_all ( ) ;
255+ }
256+
257+ _log ( str ) {
258+ if ( this . settings . DEBUG )
259+ console . log ( `[Blur my Shell > appfolders] ${ str } ` ) ;
260+ }
261+ } ;
0 commit comments