aboutsummaryrefslogtreecommitdiffstats
path: root/node_modules/xterm/src/browser/ScreenDprMonitor.ts
blob: 27ae231f0b1145e2068aed5fb8b953bbc30576ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
 * Copyright (c) 2017 The xterm.js authors. All rights reserved.
 * @license MIT
 */

import { Disposable } from 'common/Lifecycle';

export type ScreenDprListener = (newDevicePixelRatio?: number, oldDevicePixelRatio?: number) => void;

/**
 * The screen device pixel ratio monitor allows listening for when the
 * window.devicePixelRatio value changes. This is done not with polling but with
 * the use of window.matchMedia to watch media queries. When the event fires,
 * the listener will be reattached using a different media query to ensure that
 * any further changes will register.
 *
 * The listener should fire on both window zoom changes and switching to a
 * monitor with a different DPI.
 */
export class ScreenDprMonitor extends Disposable {
  private _currentDevicePixelRatio: number = window.devicePixelRatio;
  private _outerListener: ((this: MediaQueryList, ev: MediaQueryListEvent) => any) | undefined;
  private _listener: ScreenDprListener | undefined;
  private _resolutionMediaMatchList: MediaQueryList | undefined;

  public setListener(listener: ScreenDprListener): void {
    if (this._listener) {
      this.clearListener();
    }
    this._listener = listener;
    this._outerListener = () => {
      if (!this._listener) {
        return;
      }
      this._listener(window.devicePixelRatio, this._currentDevicePixelRatio);
      this._updateDpr();
    };
    this._updateDpr();
  }

  public dispose(): void {
    super.dispose();
    this.clearListener();
  }

  private _updateDpr(): void {
    if (!this._outerListener) {
      return;
    }

    // Clear listeners for old DPR
    this._resolutionMediaMatchList?.removeListener(this._outerListener);

    // Add listeners for new DPR
    this._currentDevicePixelRatio = window.devicePixelRatio;
    this._resolutionMediaMatchList = window.matchMedia(`screen and (resolution: ${window.devicePixelRatio}dppx)`);
    this._resolutionMediaMatchList.addListener(this._outerListener);
  }

  public clearListener(): void {
    if (!this._resolutionMediaMatchList || !this._listener || !this._outerListener) {
      return;
    }
    this._resolutionMediaMatchList.removeListener(this._outerListener);
    this._resolutionMediaMatchList = undefined;
    this._listener = undefined;
    this._outerListener = undefined;
  }
}