Open NilsIrl opened 4 years ago
I tried to fix this issue by applying the following patch to 5d6ab83df3f78b3678f9dffd2337d7e8d2338c65:
diff --git a/src/FirenvimElement.ts b/src/FirenvimElement.ts
index 99b3d66..8ac4bb0 100644
--- a/src/FirenvimElement.ts
+++ b/src/FirenvimElement.ts
@@ -2,7 +2,7 @@ import * as browser from "webextension-polyfill";
import { isFirefox } from "./utils/utils";
import { AbstractEditor } from "./editors/AbstractEditor";
import { getEditor } from "./editors/editors";
-import { computeSelector } from "./utils/CSSUtils";
+import { computeSelector, computeZIndex } from "./utils/CSSUtils";
export class FirenvimElement {
@@ -105,6 +105,26 @@ export class FirenvimElement {
this.span.attachShadow({ mode: "closed" }).appendChild(this.iframe);
this.getElement().ownerDocument.body.appendChild(this.span);
+ const onFocusChange = ((e: Event) => {
+ const focused = document.activeElement === this.span
+ || document.activeElement === this.iframe;
+ browser.runtime.sendMessage({
+ args: {
+ frameId: this.frameId,
+ message: {
+ args: [focused],
+ funcName: ["setFocused"],
+ }
+ },
+ funcName: ["messageFrame"],
+ });
+ this.setFrameWindowFocused(focused);
+ }).bind(this);
+ this.iframe.addEventListener("focus", onFocusChange);
+ this.iframe.addEventListener("blur", onFocusChange);
+ this.span.addEventListener("focus", onFocusChange);
+ this.span.addEventListener("blur", onFocusChange);
+
this.focus();
// We want to remove the frame from the page if the corresponding
@@ -165,6 +185,7 @@ export class FirenvimElement {
this.getElement().removeEventListener("focus", refocus);
}, 100);
refocus();
+ this.setFrameWindowFocused(true);
}
focusOriginalElement (addListener: boolean) {
@@ -212,14 +233,13 @@ export class FirenvimElement {
putEditorAtInputOrigin () {
const rect = this.editor.getElement().getBoundingClientRect();
// Save attributes
- const posAttrs = ["left", "position", "top", "zIndex"];
+ const posAttrs = ["left", "position", "top"];
const oldPosAttrs = posAttrs.map((attr: any) => this.iframe.style[attr]);
// Assign new values
this.iframe.style.left = `${rect.left + window.scrollX}px`;
this.iframe.style.position = "absolute";
this.iframe.style.top = `${rect.top + window.scrollY}px`;
- this.iframe.style.zIndex = "2147483645";
// Compare, to know whether the element moved or not
const posChanged = !!posAttrs.find((attr: any, index) =>
@@ -253,6 +273,14 @@ export class FirenvimElement {
return { dimChanged, newRect: rect };
}
+ setFrameWindowFocused (focused: boolean) {
+ if (focused) {
+ this.iframe.style.zIndex = "2147483645";
+ } else {
+ this.iframe.style.zIndex = `${computeZIndex(this.getElement()) + 1}`;
+ }
+ }
+
setPageElementContent (text: string) {
this.editor.setContent(text);
[
diff --git a/src/NeovimFrame.ts b/src/NeovimFrame.ts
index 80f1f86..c29adff 100644
--- a/src/NeovimFrame.ts
+++ b/src/NeovimFrame.ts
@@ -14,6 +14,13 @@ browser
const connectionPromise = browser.runtime.sendMessage({ funcName: ["getNeovimInstance"] });
const settingsPromise = browser.storage.local.get("globalSettings");
+function setFocusedStyle() {
+ document.documentElement.style.opacity = "1";
+}
+function setBluredStyle() {
+ document.documentElement.style.opacity = "0.5";
+}
+
window.addEventListener("load", async () => {
try {
const host = document.getElementById("host") as HTMLPreElement;
@@ -67,6 +74,13 @@ window.addEventListener("load", async () => {
const nRows = Math.floor(height / cellHeight);
nvim.ui_try_resize_grid(getGridId(), nCols, nRows);
page.resizeEditor(nCols * cellWidth, nRows * cellHeight);
+ } else if (request.funcName[0] === "setFocused") {
+ if (request.args[0]) {
+ setFocusedStyle();
+ keyHandler.focus();
+ } else {
+ setBluredStyle();
+ }
}
});
@@ -235,15 +249,15 @@ window.addEventListener("load", async () => {
}
});
// Let users know when they focus/unfocus the frame
- function setFocusedStyle() {
- document.documentElement.style.opacity = "1";
- }
- function setBluredStyle() {
- document.documentElement.style.opacity = "0.5";
- }
- window.addEventListener("focus", setFocusedStyle);
- window.addEventListener("blur", setBluredStyle);
- window.addEventListener("focus", () => keyHandler.focus());
+ window.addEventListener("focus", () => {
+ setFocusedStyle();
+ keyHandler.focus();
+ page.setFocused(true);
+ });
+ window.addEventListener("blur", () => {
+ setBluredStyle();
+ page.setFocused(false);
+ });
keyHandler.focus();
setTimeout(() => keyHandler.focus(), 10);
} catch (e) {
diff --git a/src/page/functions.ts b/src/page/functions.ts
index 6ad552d..ab95898 100644
--- a/src/page/functions.ts
+++ b/src/page/functions.ts
@@ -99,5 +99,8 @@ export function getFunctions(global: IGlobalState) {
setElementCursor: (frameId: number, line: number, column: number) => {
return global.firenvimElems.get(frameId).setPageElementCursor(line, column);
},
+ setFocused: (frameId: number, focused: boolean) => {
+ return global.firenvimElems.get(frameId).setFrameWindowFocused(focused);
+ },
};
}
diff --git a/src/utils/CSSUtils.ts b/src/utils/CSSUtils.ts
index 04fa54f..bbf6400 100644
--- a/src/utils/CSSUtils.ts
+++ b/src/utils/CSSUtils.ts
@@ -114,3 +114,12 @@ export function toCss(highlights: HighlightArray) {
`.${toHighlightClassName(id)}{background: ${elem.background || bg};color:${elem.foreground || fg};font-style:${elem.italic ? "italic" : "normal"};font-weight:${elem.bold ? "bold" : "normal"};text-decoration-line:${(elem.undercurl || elem.underline) ? "underline" : (elem.strikethrough ? "line-through" : "none")};text-decoration-style:${elem.undercurl ? "wavy" : "solid"};}`
, "");
}
+
+export function computeZIndex(e: HTMLElement, base: number = 0): number {
+ if (e === undefined || e === null) {
+ return base;
+ }
+ const index = parseInt(window.getComputedStyle(e)
+ .getPropertyValue("z-index"), 10);
+ return computeZIndex(e.parentElement, base + (isNaN(index) ? 0 : index));
+}
While this correctly places the iframe on the z-index closest to that of the editor when Firenvim is unfocused, this doesn't actually fix the problem as z-indexes are actually relative within an element. This means that for the following document:
+-----------------------------------------------------------------------------+
| body: z-index 0 |
| +-------------------------------------------------------------------------+ |
| | div: z-index 10 | |
| | +---------------------------------------------------------------------+ | |
| | | p: z-index 1000 | | |
| | +---------------------------------------------------------------------+ | |
| | +---------------------------------------------------------------------+ | |
| | | textarea: z-index 0 | | |
| | +---------------------------------------------------------------------+ | |
| +-------------------------------------------------------------------------+ |
| +-------------------------------------------------------------------------+ |
| | firenvim iframe | |
| +-------------------------------------------------------------------------+ |
+-----------------------------------------------------------------------------+
Using a z-index of 9 will place the iframe behind the div
, but using 10
or 11
will place it over both textarea
and p
.
This problem can only be solved by placing the iframe in div
, right after textarea
but we can't do that because this would disturb the page (lots of bad js rely on childElements
, nextSibling
, CSS relies on ~
, :first
, :nth-of-type
…).
So what we would need is a way to insert elements in the DOM without it being seen by the page at all. This is in theory what the shadow dom lets you do, but since you can't have an element that contains both shadow and non-shadow elements, we would need to create and insert a new node in the DOM.
In conclusion, I don't think I can solve this for now :/.
OS Version: linux x86-64
Browser Version: Firefox 72.0
Browser Addon Version: 0.1.21
Neovim Plugin Version: 0.1.21
What I tried to do:
What happened:
https://peertube.co.uk/videos/watch/993f6c52-cf25-4d4b-a8da-5490d8e63234 (https://www.codingame.com/)
Would a fix be that firenvim has the same z-index (or same + 1) as the
textarea
it is dealing about so that it stays just above it but below everything else that is above thetextarea
?