@@ -24,8 +24,9 @@ const ByteArray = imports.byteArray;
24
24
const { Atspi, GLib, Gio } = imports . gi ;
25
25
const { ClickAnimationFactory, ClickAnimationModes } = require ( "./clickAnimations.js" ) ;
26
26
const { Debouncer } = require ( "./helpers.js" ) ;
27
- const { UUID , PAUSE_EFFECTS_KEY } = require ( "./constants.js" ) ;
28
-
27
+ const { UUID , PAUSE_EFFECTS_KEY , CLICK_DEBOUNCE_MS , POINTER_WATCH_MS , IDLE_TIME } = require ( "./constants.js" ) ;
28
+ const { IdleMonitor } = require ( "./idleMonitor.js" ) ;
29
+ const { MouseMovementTracker } = require ( "./mouseMovementTracker.js" ) ;
29
30
30
31
Gettext . bindtextdomain ( UUID , `${ GLib . get_home_dir ( ) } /.local/share/locale` ) ;
31
32
@@ -37,11 +38,13 @@ function _(text) {
37
38
38
39
39
40
const ClickType = Object . freeze ( {
40
- LEFT : "left_click" ,
41
- MIDDLE : "middle_click" ,
42
- RIGHT : "right_click" ,
41
+ LEFT : "left_click" ,
42
+ MIDDLE : "middle_click" ,
43
+ RIGHT : "right_click" ,
43
44
PAUSE_ON : "pause_on" ,
44
45
PAUSE_OFF : "pause_off" ,
46
+ MOUSE_IDLE : "mouse_idle" ,
47
+ MOUSE_MOV : "mouse_mov" ,
45
48
} ) ;
46
49
47
50
@@ -52,6 +55,7 @@ class MouseClickEffects {
52
55
this . pause_icon_path = `${ this . app_icons_dir } /extra/pause.svg` ;
53
56
this . settings = this . _setup_settings ( this . metadata . uuid ) ;
54
57
this . data_dir = this . _init_data_dir ( this . metadata . uuid ) ;
58
+ this . colored_icon_store = { } ;
55
59
56
60
this . clickAnimator = ClickAnimationFactory . createForMode ( this . animation_mode ) ;
57
61
@@ -61,15 +65,18 @@ class MouseClickEffects {
61
65
return ;
62
66
}
63
67
this . animate_click ( ...args ) ;
64
- } , 10 ) ;
68
+ } , CLICK_DEBOUNCE_MS ) ;
65
69
66
70
this . listener = Atspi . EventListener . new ( this . on_mouse_click . bind ( this ) ) ;
71
+ this . idleMonitor = null ;
72
+
73
+ this . mouse_movement_tracker = null ;
67
74
68
- this . colored_icon_store = { } ;
69
75
this . enabled = false ;
76
+ this . set_active ( false ) ;
70
77
}
71
78
72
- _init_data_dir ( uuid ) {
79
+ _init_data_dir ( uuid ) {
73
80
let data_dir = `${ GLib . get_user_cache_dir ( ) } /${ uuid } ` ;
74
81
75
82
if ( GLib . mkdir_with_parents ( `${ data_dir } /icons` , 0o777 ) < 0 ) {
@@ -92,12 +99,45 @@ class MouseClickEffects {
92
99
{
93
100
key : "icon-mode" ,
94
101
value : "icon_mode" ,
95
- cb : this . update_colored_icons ,
102
+ cb : ( ) => {
103
+ this . update_colored_icons ( ) ;
104
+ if ( this . mouse_movement_tracker ) {
105
+ let icon = this . get_click_icon (
106
+ this . icon_mode ,
107
+ ClickType . MOUSE_MOV ,
108
+ this . mouse_movement_color ,
109
+ ) ;
110
+ this . mouse_movement_tracker . update ( {
111
+ icon : icon ,
112
+ } ) ;
113
+ }
114
+ } ,
96
115
} ,
97
116
{
98
117
key : "size" ,
99
118
value : "size" ,
100
- cb : null ,
119
+ cb : ( ) => {
120
+ if ( this . mouse_movement_tracker ) {
121
+ this . mouse_movement_tracker . update ( {
122
+ size : this . size ,
123
+ } ) ;
124
+ }
125
+ } ,
126
+ } ,
127
+ {
128
+ key : "idle-animation-mode" ,
129
+ value : "idle_animation_mode" ,
130
+ cb : null , // TODO
131
+ } ,
132
+ {
133
+ key : "idle-animation-period" ,
134
+ value : "idle_animation_period" ,
135
+ cb : null , // TODO
136
+ } ,
137
+ {
138
+ key : "idle-animation-delay" ,
139
+ value : "idle_animation_delay" ,
140
+ cb : null , // TODO
101
141
} ,
102
142
{
103
143
key : "left-click-effect-enabled" ,
@@ -119,6 +159,27 @@ class MouseClickEffects {
119
159
value : "pause_animation_effects_enabled" ,
120
160
cb : null ,
121
161
} ,
162
+ {
163
+ key : "mouse-movement-tracker-enabled" ,
164
+ value : "mouse_movement_tracker_enabled" ,
165
+ cb : ( ) => this . set_active ( this . enabled ) ,
166
+ } ,
167
+ {
168
+ key : "mouse-movement-tracker-persist-on-stopped-enabled" ,
169
+ value : "mouse_movement_tracker_persist_on_stopped_enabled" ,
170
+ cb : ( ) => {
171
+ if ( this . mouse_movement_tracker ) {
172
+ this . mouse_movement_tracker . update ( {
173
+ persist_on_stopped : this . mouse_movement_tracker_persist_on_stopped_enabled ,
174
+ } ) ;
175
+ }
176
+ } ,
177
+ } ,
178
+ {
179
+ key : "mouse-idle-watcher-enabled" ,
180
+ value : "mouse_idle_watcher_enabled" ,
181
+ cb : null , // TODO
182
+ } ,
122
183
{
123
184
key : "left-click-color" ,
124
185
value : "left_click_color" ,
@@ -134,10 +195,38 @@ class MouseClickEffects {
134
195
value : "right_click_color" ,
135
196
cb : this . update_colored_icons ,
136
197
} ,
198
+ {
199
+ key : "mouse-movement-color" ,
200
+ value : "mouse_movement_color" ,
201
+ cb : ( ) => {
202
+ this . update_colored_icons ( ) ;
203
+ if ( this . mouse_movement_tracker ) {
204
+ let icon = this . get_click_icon (
205
+ this . icon_mode ,
206
+ ClickType . MOUSE_MOV ,
207
+ this . mouse_movement_color ,
208
+ ) ;
209
+ this . mouse_movement_tracker . update ( {
210
+ icon : icon ,
211
+ } ) ;
212
+ }
213
+ } ,
214
+ } ,
215
+ {
216
+ key : "mouse-idle-watcher-color" ,
217
+ value : "mouse_idle_watcher_color" ,
218
+ cb : this . update_colored_icons ,
219
+ } ,
137
220
{
138
221
key : "general-opacity" ,
139
222
value : "general_opacity" ,
140
- cb : null ,
223
+ cb : ( ) => {
224
+ if ( this . mouse_movement_tracker ) {
225
+ this . mouse_movement_tracker . update ( {
226
+ opacity : this . general_opacity ,
227
+ } ) ;
228
+ }
229
+ } ,
141
230
} ,
142
231
{
143
232
key : "animation-mode" ,
@@ -156,13 +245,13 @@ class MouseClickEffects {
156
245
} ,
157
246
] ;
158
247
159
- bindings . forEach ( b => settings . bind (
248
+ bindings . forEach ( b => settings . bind (
160
249
b . key ,
161
250
b . value ,
162
251
b . cb ? ( ...args ) => b . cb . call ( this , ...args ) : null ,
163
252
) ) ;
164
253
165
- return settings ;
254
+ return settings ;
166
255
}
167
256
168
257
enable ( ) {
@@ -177,12 +266,12 @@ class MouseClickEffects {
177
266
178
267
set_keybindings ( ) {
179
268
this . unset_keybindings ( ) ;
180
- Main . keybindingManager . addHotKey (
269
+ Main . keybindingManager . addHotKey (
181
270
PAUSE_EFFECTS_KEY ,
182
271
this . pause_effects_binding ,
183
- this . on_pause_toggled . bind ( this ) ,
272
+ this . on_pause_toggled . bind ( this ) ,
184
273
) ;
185
- }
274
+ }
186
275
187
276
on_pause_toggled ( ) {
188
277
this . set_active ( ! this . enabled ) ;
@@ -197,22 +286,22 @@ class MouseClickEffects {
197
286
}
198
287
}
199
288
200
- get_click_icon ( mode , click_type , color ) {
201
- let name = `${ mode } _${ click_type } _${ color } ` ;
202
- let path = `${ this . data_dir } /icons/${ name } .svg ` ;
289
+ get_click_icon ( mode , click_type , color ) {
290
+ let name = `${ mode } _${ click_type } _${ color } .svg ` ;
291
+ let path = `${ this . data_dir } /icons/${ name } ` ;
203
292
return this . get_icon_cached ( path ) ;
204
293
}
205
294
206
295
get_icon_cached ( path ) {
207
296
if ( this . colored_icon_store [ path ] )
208
297
return this . colored_icon_store [ path ] ;
209
298
210
- if ( GLib . file_test ( path , GLib . FileTest . IS_REGULAR ) ) {
299
+ if ( GLib . file_test ( path , GLib . FileTest . IS_REGULAR ) ) {
211
300
this . colored_icon_store [ path ] = Gio . icon_new_for_string ( path ) ;
212
301
return this . colored_icon_store [ path ] ;
213
302
}
214
303
215
- return null ;
304
+ return null ;
216
305
}
217
306
218
307
disable ( ) {
@@ -232,37 +321,72 @@ class MouseClickEffects {
232
321
this . create_icon_data ( ClickType . LEFT , this . left_click_color ) ;
233
322
this . create_icon_data ( ClickType . MIDDLE , this . middle_click_color ) ;
234
323
this . create_icon_data ( ClickType . RIGHT , this . right_click_color ) ;
324
+ this . create_icon_data ( ClickType . MOUSE_IDLE , this . mouse_idle_watcher_color ) ;
325
+ this . create_icon_data ( ClickType . MOUSE_MOV , this . mouse_movement_color ) ;
235
326
}
236
327
237
328
set_active ( enabled ) {
238
329
this . enabled = enabled ;
330
+
239
331
this . listener . deregister ( 'mouse' ) ;
332
+ if ( this . mouse_movement_tracker ) {
333
+ this . mouse_movement_tracker . finalize ( ) ;
334
+ this . mouse_movement_tracker = null ;
335
+ }
336
+ if ( this . idleMonitor ) {
337
+ this . idleMonitor . finalize ( ) ;
338
+ this . idleMonitor = null ;
339
+ }
240
340
241
341
if ( enabled ) {
242
342
this . listener . register ( 'mouse' ) ;
243
- global . log ( UUID , "Click effects activated" ) ;
343
+
344
+ if ( this . mouse_movement_tracker_enabled ) {
345
+ const icon = this . get_click_icon ( this . icon_mode , ClickType . MOUSE_MOV , this . mouse_movement_color ) ;
346
+ this . mouse_movement_tracker = new MouseMovementTracker (
347
+ icon , this . size , this . general_opacity ,
348
+ this . mouse_movement_tracker_persist_on_stopped_enabled ) ;
349
+ this . mouse_movement_tracker . start ( ) ;
350
+ }
351
+
352
+ // TODO
353
+ // if (this.mouse_idle_watcher_enabled) {
354
+ // // XXX: only enable according w respective settings
355
+ // this.idleMonitor = new IdleMonitor({
356
+ // idle_delay: IDLE_TIME,
357
+ // on_idle: this.on_idle_handler,
358
+ // on_active: this.on_active_handler,
359
+ // on_finish: this.on_finish_handler,
360
+ // });
361
+ // this.idleMonitor.start();
362
+ // }
363
+
364
+ global . log ( UUID , "activated" ) ;
244
365
} else {
245
- global . log ( UUID , "Click effects deactivated" ) ;
366
+ global . log ( UUID , "deactivated" ) ;
246
367
}
247
368
}
248
369
249
370
create_icon_data ( click_type , color ) {
250
371
if ( this . get_click_icon ( this . icon_mode , click_type , color ) )
251
372
return true ;
252
373
253
- let source = Gio . File . new_for_path ( `${ this . app_icons_dir } /${ this . icon_mode } .svg` ) ;
374
+ let source = Gio . File . new_for_path ( `${ this . app_icons_dir } /${ this . icon_mode } .svg` ) ;
254
375
let [ l_success , contents ] = source . load_contents ( null ) ;
255
376
256
377
contents = ByteArray . toString ( contents ) ;
257
378
contents = contents . replace ( 'fill="#000000"' , `fill="${ color } "` ) ;
258
379
259
- let name = `${ this . icon_mode } _${ click_type } _${ color } ` ;
260
- let dest = Gio . File . new_for_path ( `${ this . data_dir } /icons/${ name } .svg` ) ;
380
+ let name = `${ this . icon_mode } _${ click_type } _${ color } .svg` ;
381
+ let path = `${ this . data_dir } /icons/${ name } ` ;
382
+ let dest = Gio . File . new_for_path ( path ) ;
261
383
262
384
if ( ! dest . query_exists ( null ) )
263
385
dest . create ( Gio . FileCreateFlags . NONE , null ) ;
264
386
265
387
let [ r_success , tag ] = dest . replace_contents ( contents , null , false , Gio . FileCreateFlags . REPLACE_DESTINATION , null ) ;
388
+
389
+ if ( r_success ) global . log ( UUID , `created colored icon cache for ${ name } ` ) ;
266
390
return r_success ;
267
391
}
268
392
@@ -315,16 +439,16 @@ class MouseClickEffects {
315
439
let extension = null ;
316
440
317
441
function enable ( ) {
318
- extension . enable ( ) ;
442
+ extension . enable ( ) ;
319
443
}
320
444
321
445
function disable ( ) {
322
- extension . disable ( ) ;
323
- extension = null ;
446
+ extension . disable ( ) ;
447
+ extension = null ;
324
448
}
325
449
326
450
function init ( metadata ) {
327
- if ( ! extension ) {
451
+ if ( ! extension ) {
328
452
Atspi . init ( ) ;
329
453
extension = new MouseClickEffects ( metadata ) ;
330
454
} ;
0 commit comments