I have the following basic setup
const St = imports.gi.St;
const Webkit = imports.gi.WebKit2;
const Gtk = imports.gi.Gtk;
let window, webView;
function _handleclick(){
window = new Gtk.Window({
type: Gtk.WindowType.TOPLEVEL
decorated: false,
skip_taskbar_hint: true,
skip_pager_hint: true,
resizable: false,
});
window.set_default_size(400, 600);
webView = new Webkit.WebView();
webView.load_uri(https://www.example.com);
window.add(webView);
window.set_position(Gtk.WindowPosition.MOUSE);
window.show_all();
}
The function is called when the user clicks a St.Bin object, defined like this
button = new St.Bin({
style_class: 'panel-button',
reactive: true,
can_focus: true,
x_expand: true,
y_expand: false,
track_hover: true
});
when this function is called, the Gtk.Window containing the WebView is drawn successfully, and the website displayed can be focused and interacted with using the keyboard (tab, enter, alt+tab, etc.) but it doesn't appear to pick up any mouse events. Even though clicking on the window will allow it to grab focus, the elements of the displayed website do not respond to any mouse interaction, be it clicking or scrolling.
I've been going over the documentation for both WebView and Window, according to the former, "WebKitWebView is scrollable by itself", which seems to imply that it should already be listening for mouse events, and from my spotty understanding of this article on Gtk event propagation, since the window has focus, it should be propagating the events to the GtkWidget; clearly there's something I'm failing to understand here or perhaps the mouse event is being picked up by something else? The website show in the webview seems to receive an event when the mouse pointer enters or exits the webview area, but no button presses or other movement.
I have tried fumbling around with a bunch of direrent attibutes and functions I've found in the documentation but every resource online would seem to indicate that the basic setup of a webview inside a gtk window should work without further tweaking.
Related
I am using the LightGallery lightbox lib to play a video (using video.js) in an iframe. The esc key is used to close the LightGallery instance. This works fine until the user interacts with the video controls since those are given focus.
How can I restore focus to the LightGallery instance after these interactions?
I've been poking around video.js and am able to trap these user clicks but so far I haven't been able to figure out what I need to do to return focus so the esc key works. I've tried using postMessage, blur and everything else I could think of and I'm a little lost. Am I asking the wrong question/looking at the wrong thing?
Various attempts:
player.on('click', function (evt) {
console.log('iframe window', window.frameElement);
evt.currentTarget.blur();
window.postMessage("hello", "*")
// var lg = document.getElementById('vidContainer');
// var lg = document.getElementsByClassName('lightGallery');
// console.log('lg', lg);
// console.log('document', document);
// lg.focus()
});
So I resolved the "focus" issue in what may be a really hacky way but it seems to work to insure that the lightbox close button can always be triggered by the escape key,
When the iframe loads, store a reference to the close button in the parent window.
let closeBtn
window.onload = function () {
closeBtn = parent.document.getElementsByClassName("lg-close lg-icon")[0]
}
Add a click event handler to the Videojs instance and use it to reassert focus on the close button after the user has interacted with the video controls. Not great, not accessibility friendly but this is what the client is expecting.
player.on('click', function (evt) {
closeBtn.focus();
});
I am currently developing the login aspect inside a custom browser on ios. I want to open the keyboard when a user clicks on an input element. When an input element gets clicked, I set the 'autofocus' attribute for that element, followed by a focus on the element. However, these steps are not sufficient for opening the keyboard.
I have tried methods present in the link: IOS show keyboard on input focus, but nothing works.
The software version I'm working with is 14.4.2.
I am testing the app on an iPad.
var ev = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': true,
'screenX': x,
'screenY': y
});
//x and y are the screen coordinates of the point where a user clicks.
var el = document.elementFromPoint(x, y);
console.log("Clicked element: "+el); //print element to console
el.addEventListener('click', function() {
el.setAttribute('autofocus', 'autofocus');
el.focus();
});
el.dispatchEvent(ev);
If you are testing your app in Simulator , make sure I/O -> Keyboard -> Connect Hardware Keyboard is unchecked. Otherwise, you won't see the keyboard appear.
Programmatic focus using element.focus() doesn't trigger the system-level keyboard to open because WKWebView only shows the keyboard if the focus is initiated by a user.
When the focus is triggered during user script evaluation, it is not considered as user interaction.
WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=243416
Changes done by Apple developers here: https://github.com/WebKit/WebKit/pull/2907
The changes are still in beta mode and have not yet been rolled out to the latest iPad OS version.
So, I have web page that opens another page (browser tab) as a child to the first. The parent tab holds the code that performs the bulk of the application's work. The child tab holds a component that is normally embedded in the parent tab, but sometimes the user may want to open it in its own tab. So they can.
The problem is, the component in the child tab supports about 20 different keyboard commands and a number of mouse related commands (as combos with keyboard commands). I was trying to avoid remapping each keyboard command in the child window to a call in the parent window. Right now, in the parent window, I use a plugin to map and handle keyboard commands that all get sent to the right component API call.
What I want to do, is to just pipe keyboard and mouse events from the child window back to the parent, so that the regular handling of those events can proceed as normal. I don't want to have to setup specific handlers for every command all over again in the child window. Piping the key/mouse events feels more elegant, and would, ideally, take less code.
The first thing I tried, is this:
// CHILD WINDOW
window.document.addEventListener("keydown", Redispatch, false);
function Redispatch(event){
window.opener.myRedirector.dispatchChildEvent(event);
}
And in the parent window, it had this:
myRedirector.dispatchChildEvent = function(event){
var r = dispatchEvent(e);
console.log('dispatched event from child window');
}
In this case, nothing happens. The console.log() function in the parent window never fires, and stepping through it, the console.log() line never gets hit. The dispatchEvent(e) call behaves as though an error occurs, but nothing is thrown (this is the latest Chrome).
So I tried instantiating a new event in the parent like this (seen from another StackOverflow post):
myRedirector.dispatchChildEvent = function(e){
var event = document.createEvent('KeyboardEvent');
var method = typeof event.initKeyboardEvent !== 'undefined' ? "initKeyboardEvent" : "initKeyEvent";
event[method](
/* type */ e.type,
/* bubbles */ true,
/* cancelable */ false,
/* view */ window,
/* keyIdentifier*/ e.keyIdentifier,
/* keyLocation */ e.location,
/* ctrlKey */ e.ctrlKey,
/* altKey */ e.altKey,
/* shiftKey */ e.shiftKey,
/* metaKey */ e.metaKey,
/* altGraphKey */ false
);
}
The problem here is that this doesn't initialize all the properties of the event, like keyCode and which. The keyboard handler plugin I am using doesn't read keyIdentifier, it uses keyCode. I can't manually set keyCode cause it's readonly on the object. I thought of changing the plugin to read the keyIdentifier, but that value isn't an integer, it's a Unicode string like "U+005", etc, and I don't want to remap all the keyCodes to those values in the plugin (though this may be Chrome specific).
So I also tried instantiating a CustomEvent, and just adding properties to it, which almost worked. Except CustomEvent has a type property that is set to empty string, and can't be overridden, so the plugin doesn't catch it since it's not of type 'keydown', etc.
I keep feeling like I'm missing something that should make this possible. That's why I've avoided other solutions like remapping values, or setting up all new handlers in the child window, etc.
It feels like it should be possible to just pipe keyboard/mouse events to a parent window. So far, though, I can't seem to find a way.
Any suggestions, or solutions?
So, I was using document.createEvent() and that was producing an event object with too many properties already added (that were read-only). So when I did this:
var event = new Event(childEvent.type);
This created an event of the right type, but with no keyCode or keyIdentifier, or other such properties, and I could just add them dynamically from the childEvent. Then, dispatching them worked fine.
It seems that Google+ checks for notification updates when I activate the tab in Firefox
It'd show "0" every time I activate it, but change to a number of new notifications in a couple of seconds after that.
What's the mechanism allowing to tap into that event? Is there a specific DOM event for that? Or are they using something like onmouseover handler and just consider any kind of activity to be a sufficient indicator of tab activation?
Just a guess because I haven't all relevant browsers available for testing.
What about using the focus event on the window. Whenever a user clicks somewhere this is invoked but also on switching of tabs. To distinguish between a user's actions on the page and a user switching to the page you could check if the event's explicitOriginalTarget points to the window.
window.onfocus=function(event){
if(event.explicitOriginalTarget===window){
console.log('switched from tab');
}
}
There is Page visibility document, which describes document.onvisibilitychange event handler.
The usage
document.onvisibilitychange = function() {
console.log("Visibility of page has changed!");
};
Unfortunately there's no 100% accurate solution
onvisibilitychange correctly triggers on tab changes, but does not trigger on window changes (ALT+TAB) visibilitychange event is not triggered when switching program/window with ALT+TAB or clicking in taskbar
window.onfocus triggers when the document becomes focused. This works as expected if the tab's focus is already inside the web page, then it correctly triggers when window or tab becomes focused.
But if you have the focus on the URL bar, or in the console, you are already "out of focus", and when you get out of the window or tab and return, you will remain "out of focus", so this event won't trigger until you click inside the page, or navigate into it through TAB key
You can test below how each event triggers (click inside the white iframe to test onfocus/onblur events)
window.onfocus = () => console.log("focus");
window.onblur = () => console.log("out of focus");
document.onvisibilitychange = () => console.log("visibilityState: ", document.visibilityState);
Is it possible to determine whether a user is active on the current web page or, say, focused on a different tab or window?
It seems that if you switch tabs, any JavaScript set on a timeout/interval continues running. It would be nice to be able to 'pause' the events when the user is not on the page.
Would something like attaching a mouseover event to the body work, or would that be too resource-intensive?
You can place onfocus/onblur events on the window.
There's wide support for those events on the window.
Example: http://jsfiddle.net/xaTt4/
window.onfocus = function() {
// do something when this window object gets focus.
};
window.onblur = function() {
// do something when this window object loses focus.
};
Open Web Analytics (and perhaps some other tracking tools) has action tracking
You could keep an alive variable going using mousemove events (assuming the user does not leave the mouse still on the page). When this variable (a timestamp likely) has not been updated in x seconds, you could say the page is not active and pause any script.
As long as you do not do a lot of processing in the body event handler you should be okay. It should just update the variable, and then have a script poll it at a certain interval to do the processing/checks (say every 1000ms).
Attach listeners to mousemove, keyup and scroll to the document.
I use this throttle/debounce function (which works without jQuery, even though it's a jQuery plugin if jQuery is present) to only run code in response to them once in ~250ms, so that you're not firing some code on every pixel of the mouse moving.
You can also use the visibilityState of the document:
document.addEventListener("visibilitychange", function() {
if( document.visibilityState === 'visible' ) {
// Do your thing
}
});
There is a wide acceptance of this API.