Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webview keeps losing focus

I have an app that is basically just a wrapper for an internal company website. The idea is to easily load the website in its own window on my Chromebook, that way it won't unload when RAM gets low.

I have a very simple app with a single WebView that consumes an entire app window. The problem is, whenever I switch away from the window and come back, the webview has lost focus. This is particularly annoying because it's a chat app, and I'd like to start talking immediately upon alt-tabbing back to the window.

I've looked into focusing the webview each time the window receives focus, but the disconnect between Window (from chrome.windows) and AppWindow (from chrome.app.window) makes this nontrivial. The event that I need only exists for Window objects, but I can only definitively obtain the current AppWindow. I could theoretically get the currently active Window when the app first launches, but that seems hackish and unreliable.

index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Chat App</title>
    <link rel="stylesheet" href="styles.css">
  </head>

  <body>
    <webview src="https://example.com/" id="chat"></webview>
  </body>
</html>

background.js

chrome.app.runtime.onLaunched.addListener(function(launchData) {
  chrome.app.window.create(
    'index.html',
    {
      id: 'chat'
    }
  );
});

styles.css

Making the webview consume the entire window was a bit tricky; I had to use some redundant CSS properties to get it to work properly.

html, body {
  margin: 0;
  padding: 0;
  overflow: hidden;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}

#chat {
  border: 0 none;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}
like image 889
Zenexer Avatar asked Jun 30 '15 20:06

Zenexer


1 Answers

You can achieve this simply with the Page Visibility API. You can use it to add an event listener and check the document.hidden state to return focus to the chat box. You can also do other things, like play an audio alert when you receive chat messages when the tab is not visible.

In this example, I've also added an event listener to the first chat box so if focus is lost, it tries to get it again. This is a rather heavy-handed approach, but you can adjust your logic to suit requirements.

JSFiddle

function handleVisibilityChange() {
    console.log(document.hidden);
    if (!document.hidden) {
        chatFocus();
    }
}

function chatFocus() {
    document.getElementById("ChatBox1").focus();
}

document.addEventListener("visibilitychange", handleVisibilityChange, false);
document.getElementById("ChatBox1").addEventListener("blur", chatFocus, true);
<input type="text" id="ChatBox1" placeholder="ChatBox1">
<input type="text" id="ChatBox2" placeholder="ChatBox2">

Testing this on Chrome, you'll find that if you switch to another tab, or minimize the window, the visibilitychange event will be fired. If you just switch to another window, though, it won't consider the page to be hidden. You can also make use of window.onblur to listen for when the page loses focus in general.

PS. About your 'tricky' redundant CSS: specifying left: 0 and width: 100% should be all you need (right: 0 shouldn't be necessary), but in addition to that, text fields tend to have border and padding etc. so in order to ensure the field doesn't end up wider than its container, you need to set box-sizing: border-box so that padding and borders are included when determining its size. It's a trick that solves many problems in CSS.

like image 90
BoffinBrain Avatar answered Oct 22 '22 00:10

BoffinBrain