diff options
author | Kristóf Marussy <kristof@marussy.com> | 2022-02-27 18:15:43 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2022-03-06 18:56:48 +0100 |
commit | c80aad5b4ab70462f39b5073c936adf9f54c5fd3 (patch) | |
tree | 23d37d3d7564f9dcac442adeafe4ef9c7e9bedd6 /packages/service-preload | |
parent | feat: Location bar actions (diff) | |
download | sophie-c80aad5b4ab70462f39b5073c936adf9f54c5fd3.tar.gz sophie-c80aad5b4ab70462f39b5073c936adf9f54c5fd3.tar.zst sophie-c80aad5b4ab70462f39b5073c936adf9f54c5fd3.zip |
fix(service-preload): Browser view canvas background
Due to `BrowserView.setBackgroundColor` not working under linux, we have
to inject styles to make sure our `BrowserView` is opaque.
We try to cover more edge cases to avoid the interference of the
injected style and the web site's own styles according to the CSS
specification:
https://www.w3.org/TR/css-backgrounds-3/#body-background
In particular, we avoid overwriting the styles for the `html` element
if `body` already has an opaque background so that the background of
`body` can extend to the whole canvas.
This might still interfere with the web site if it updates the
background color on the fly (dark mode), but a reload should solve
most of such issues.
Hopefully, after
https://github.com/electron/electron/issues/32898
is resolved, we can get rid of the hack entirely.
Signed-off-by: Kristóf Marussy <kristof@marussy.com>
Diffstat (limited to 'packages/service-preload')
-rw-r--r-- | packages/service-preload/package.json | 4 | ||||
-rw-r--r-- | packages/service-preload/src/index.ts | 53 |
2 files changed, 56 insertions, 1 deletions
diff --git a/packages/service-preload/package.json b/packages/service-preload/package.json index 1cfa74c..2090cf9 100644 --- a/packages/service-preload/package.json +++ b/packages/service-preload/package.json | |||
@@ -9,6 +9,10 @@ | |||
9 | }, | 9 | }, |
10 | "dependencies": { | 10 | "dependencies": { |
11 | "@sophie/service-shared": "workspace:*", | 11 | "@sophie/service-shared": "workspace:*", |
12 | "color-string": "^1.9.0", | ||
12 | "electron": "17.1.0" | 13 | "electron": "17.1.0" |
14 | }, | ||
15 | "devDependencies": { | ||
16 | "@types/color-string": "^1" | ||
13 | } | 17 | } |
14 | } | 18 | } |
diff --git a/packages/service-preload/src/index.ts b/packages/service-preload/src/index.ts index fb19107..a49a3a4 100644 --- a/packages/service-preload/src/index.ts +++ b/packages/service-preload/src/index.ts | |||
@@ -19,12 +19,63 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | import { ServiceToMainIpcMessage, WebSource } from '@sophie/service-shared'; | 21 | import { ServiceToMainIpcMessage, WebSource } from '@sophie/service-shared'; |
22 | import colorString from 'color-string'; | ||
22 | import { ipcRenderer, webFrame } from 'electron'; | 23 | import { ipcRenderer, webFrame } from 'electron'; |
23 | 24 | ||
25 | const DEFAULT_BG_COLOR = '#fff'; | ||
26 | |||
27 | /** | ||
28 | * Styles a HTML element such that its background is opaque. | ||
29 | * | ||
30 | * If there is an existing background color, it will be made maximally opaque. | ||
31 | * | ||
32 | * If there is a background image, transparent areas will be colored `DEFAULT_BG_COLOR`. | ||
33 | * | ||
34 | * If the element was completely transparent, the function returns `false` instead. | ||
35 | * This allows leaving a `html` element transparent to let the background of the `body` | ||
36 | * element render in its palce. | ||
37 | * | ||
38 | * @param element The HTML element to style. | ||
39 | * @returns `true` if the background was made opaque. | ||
40 | * @see https://www.w3.org/TR/css-backgrounds-3/#body-background | ||
41 | */ | ||
42 | function tryMakeOpaque(element: HTMLElement): boolean { | ||
43 | const style = getComputedStyle(element); | ||
44 | const bgColor = colorString.get.rgb(style.backgroundColor); | ||
45 | if (bgColor[3] > 0) { | ||
46 | if (bgColor[3] < 1) { | ||
47 | bgColor[3] = 1; | ||
48 | // eslint-disable-next-line no-param-reassign -- Deliberately add element style. | ||
49 | element.style.backgroundColor = colorString.to.rgb(bgColor); | ||
50 | } | ||
51 | return true; | ||
52 | } | ||
53 | if (style.backgroundImage !== 'none') { | ||
54 | // eslint-disable-next-line no-param-reassign -- Deliberately add element style. | ||
55 | element.style.backgroundColor = DEFAULT_BG_COLOR; | ||
56 | return true; | ||
57 | } | ||
58 | return false; | ||
59 | } | ||
60 | |||
24 | if (webFrame.parent === null) { | 61 | if (webFrame.parent === null) { |
25 | // Inject CSS to simulate `browserView.setBackgroundColor`. | 62 | // Inject CSS to simulate `browserView.setBackgroundColor`. |
26 | // This is injected before the page loads, so the styles from the website will overwrite it. | 63 | // This is injected before the page loads, so the styles from the website will overwrite it. |
27 | webFrame.insertCSS('body { background-color: #fff; }'); | 64 | document.addEventListener('DOMContentLoaded', () => { |
65 | if ( | ||
66 | document.documentElement.style.contain === '' && | ||
67 | document.body.style.contain === '' | ||
68 | ) { | ||
69 | if ( | ||
70 | !tryMakeOpaque(document.documentElement) && | ||
71 | !tryMakeOpaque(document.body) | ||
72 | ) { | ||
73 | document.body.style.backgroundColor = DEFAULT_BG_COLOR; | ||
74 | } | ||
75 | } else if (!tryMakeOpaque(document.documentElement)) { | ||
76 | document.documentElement.style.backgroundColor = DEFAULT_BG_COLOR; | ||
77 | } | ||
78 | }); | ||
28 | } | 79 | } |
29 | 80 | ||
30 | /** | 81 | /** |