Skip to content

Commit a6b51d9

Browse files
committed
Fix: Preliminary fix for the log spam of the clipboard module.
1 parent f3366f1 commit a6b51d9

1 file changed

Lines changed: 81 additions & 14 deletions

File tree

gnome-extensions/extension/features/Clipboard/tabClipboard.js

Lines changed: 81 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ export const ClipboardTabContent = GObject.registerClass(
5252
this._imagePreviewSize = this._settings.get_int('clipboard-image-preview-size');
5353
this._layoutMode = this._settings.get_string('clipboard-layout-mode') || 'list';
5454
this._hasRenderedOnce = false;
55+
this._isDestroyed = false;
56+
this._deferredRedrawPending = false;
57+
this._redrawIdleId = 0;
58+
this._redrawScheduled = false;
59+
this._retryId = 0;
60+
this._settingSignalIds = [];
61+
this._managerSignalIds = [];
62+
this._actorSignalIds = [];
5563

5664
this._copyService = new ClipboardCopyService();
5765
this._selectionService = new ClipboardSelectionService();
@@ -73,6 +81,12 @@ export const ClipboardTabContent = GObject.registerClass(
7381

7482
this._setupSettingsSignals();
7583
this._connectManagerSignals();
84+
this._actorSignalIds.push(this.connect('notify::mapped', () => this._flushDeferredRedraw()));
85+
this._actorSignalIds.push(this.connect('notify::visible', () => this._flushDeferredRedraw()));
86+
this.connect('destroy', () => {
87+
this._isDestroyed = true;
88+
this._clearRedrawSources();
89+
});
7690
}
7791

7892
// ========================================================================
@@ -293,16 +307,22 @@ export const ClipboardTabContent = GObject.registerClass(
293307
* @private
294308
*/
295309
_scheduleRedraw(immediate = false) {
310+
if (this._isDestroyed) return;
311+
296312
if (!this._canRenderNow()) {
297313
this._deferredRedrawPending = true;
298-
this._ensureRetry();
314+
if (this._shouldRetryRender()) this._ensureRetry();
299315
return;
300316
}
301317

302318
this._deferredRedrawPending = false;
303319

304320
if (immediate) {
305-
if (this._redrawIdleId) GLib.source_remove(this._redrawIdleId);
321+
if (this._redrawIdleId) {
322+
GLib.source_remove(this._redrawIdleId);
323+
this._redrawIdleId = 0;
324+
this._redrawScheduled = false;
325+
}
306326
this._redraw();
307327
return;
308328
}
@@ -325,21 +345,36 @@ export const ClipboardTabContent = GObject.registerClass(
325345
* @private
326346
*/
327347
_canRenderNow() {
328-
if (!this._currentView || !this._scrollView || !this.mapped || !this.visible) return false;
348+
if (!this._shouldRetryRender()) return false;
329349
const box = this._scrollView.get_allocation_box();
330350
return box && box.get_width() > 1 && box.get_height() > 1;
331351
}
332352

353+
/**
354+
* Determine if a pending render should wait for allocation.
355+
*
356+
* @returns {boolean} True if the actor is alive and visible.
357+
* @private
358+
*/
359+
_shouldRetryRender() {
360+
return !this._isDestroyed && !!this._currentView && !!this._scrollView && this.mapped && this.visible;
361+
}
362+
333363
/**
334364
* Ensure redraw is retried when rendering becomes possible again.
335365
*
336366
* @private
337367
*/
338368
_ensureRetry() {
339-
if (this._retryId) return;
369+
if (this._isDestroyed || this._retryId) return;
340370

341371
this._retryId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, RETRY_INTERVAL_MS, () => {
342-
if (!this._deferredRedrawPending || !this._currentView) {
372+
if (this._isDestroyed || !this._deferredRedrawPending || !this._currentView) {
373+
this._retryId = 0;
374+
return GLib.SOURCE_REMOVE;
375+
}
376+
377+
if (!this._shouldRetryRender()) {
343378
this._retryId = 0;
344379
return GLib.SOURCE_REMOVE;
345380
}
@@ -354,15 +389,27 @@ export const ClipboardTabContent = GObject.registerClass(
354389
});
355390
}
356391

392+
/**
393+
* Render pending content when a cached tab becomes visible.
394+
*
395+
* @private
396+
*/
397+
_flushDeferredRedraw() {
398+
if (this._isDestroyed || !this._deferredRedrawPending || !this._shouldRetryRender()) return;
399+
this._scheduleRedraw(true);
400+
}
401+
357402
/**
358403
* Perform the actual redraw of the current view.
359404
*
360405
* @private
361406
*/
362407
_redraw() {
408+
if (this._isDestroyed) return;
409+
363410
if (!this._canRenderNow()) {
364411
this._deferredRedrawPending = true;
365-
this._ensureRetry();
412+
if (this._shouldRetryRender()) this._ensureRetry();
366413
return;
367414
}
368415

@@ -391,6 +438,8 @@ export const ClipboardTabContent = GObject.registerClass(
391438
* Handle the event when the clipboard tab is selected.
392439
*/
393440
onTabSelected() {
441+
if (this._isDestroyed) return;
442+
394443
const needs = this._deferredRedrawPending || this._searchService.pendingReset || !this._hasRenderedOnce;
395444

396445
this._searchService.onTabSelected(this._searchComponent);
@@ -427,19 +476,33 @@ export const ClipboardTabContent = GObject.registerClass(
427476
* Handle the event when the extension menu is closed.
428477
*/
429478
onMenuClosed() {
430-
this._deferredRedrawPending = false;
479+
if (this._isDestroyed) return;
480+
431481
this._searchService.onMenuClosed();
482+
this._clearRedrawSources();
483+
484+
const currentFocus = global.stage.get_key_focus();
485+
if (currentFocus && (currentFocus === this || this.contains(currentFocus))) {
486+
global.stage.set_key_focus(null);
487+
}
488+
}
432489

490+
/**
491+
* Remove pending redraw sources.
492+
*
493+
* @private
494+
*/
495+
_clearRedrawSources() {
433496
if (this._redrawIdleId) {
434497
GLib.source_remove(this._redrawIdleId);
435498
this._redrawIdleId = 0;
436-
this._redrawScheduled = false;
437499
}
438-
439-
const currentFocus = global.stage.get_key_focus();
440-
if (currentFocus && (currentFocus === this || this.contains(currentFocus))) {
441-
global.stage.set_key_focus(null);
500+
if (this._retryId) {
501+
GLib.source_remove(this._retryId);
502+
this._retryId = 0;
442503
}
504+
this._redrawScheduled = false;
505+
this._deferredRedrawPending = false;
443506
}
444507

445508
// ========================================================================
@@ -450,8 +513,8 @@ export const ClipboardTabContent = GObject.registerClass(
450513
* Clean up resources and disconnect signals before destruction.
451514
*/
452515
destroy() {
453-
if (this._redrawIdleId) GLib.source_remove(this._redrawIdleId);
454-
if (this._retryId) GLib.source_remove(this._retryId);
516+
this._isDestroyed = true;
517+
this._clearRedrawSources();
455518

456519
this._copyService?.destroy();
457520

@@ -460,6 +523,10 @@ export const ClipboardTabContent = GObject.registerClass(
460523

461524
this._settingSignalIds.forEach((id) => this._settings.disconnect(id));
462525
this._managerSignalIds?.forEach((id) => this._manager.disconnect(id));
526+
this._actorSignalIds.forEach((id) => this.disconnect(id));
527+
this._settingSignalIds = [];
528+
this._managerSignalIds = [];
529+
this._actorSignalIds = [];
463530

464531
this._searchComponent?.destroy();
465532
this._actionBar?.destroy();

0 commit comments

Comments
 (0)