Window.opener.focus () does not work

I can't get this to work.

In response to a click, window A opens window B (which then has focus). Then, in response to clicking on B, the window calls window.opener.focus() , but the focus does not return to A.

I found a weird, weird workaround for Chrome (29, maybe others). If I run:

 window.opener.name = 'somename'; window.open(window.opener.location.href, window.opener.name); window.opener.focus(); 

it works (and does not restart window A). But this does not work for Firefox, and it is probably all the same.

It seems to me very clear what to do opener and focus , but window.opener.focus() does not work. What am I missing?

+6
source share
3 answers

From the exact guide :

Makes a request to bring the window forward. It may fail due to user settings, and the window does not guarantee that it will be front before this method returns.

The emphasis is mine. The focus() call is just a request, and the browser can ignore you, and you should usually ignore it. Think about what kinds of vile things you can get by switching focus to a tiny window when someone types, if you need some reasons why the browser ignores your request.

If you need focus() for your application to work, you need to reconfigure your application so that it does not need to call focus() .

+5
source

I see why the browser / OS does not allow child windows to capture focus (abuse of power). Here is a workaround:

  • In the parent window, declare a function in "window.external" that will call Javascript "alert ()" or "confirm ()".
  • Call this function from the child window.
  • The browser can ignore the request from the child window that wants to control focus (for example, window.opener.focus ()), but the browser must honor the request from the parent window, which causes a warning () or confirmation (), which requires focusing on the parent window .

JS Parent:

  var child = window.open('child.html', 'child'); window.external.comeback = function() { var back = confirm('Are you sure you want to comback?'); if(back) { child.close(); } else { child.focus(); } } 

JS Baby:

  // assuming you have jQuery $('.btn').click() { window.opener.external.comeback(); }; 

β€œI use this code in a real-world application to process a validation request that runs in a child window, and I need to gracefully return to the parent window.”

See: SimplifySites.com

+3
source

Web page or private intranet?

Window management is browser and OS dependent. HTML and ECMAscript have nothing to say about this.

If this is for a public website, then just don’t worry - as they say, "Do not break the network."

But I really want to!

If this is for some strictly managed (for example, intranet) application, then you need to resort to writing add-ons / extensions. It is definitely easier if you can limit yourself to a single browser and platform.

EDIT : Example for Firefox on Win32 ...

This solution works as a custom add-on for Firefox, which uses jsctypes internally to load the Win32 DLL. The JavaScript function window_focus() , which does what you want.

There are three parts to this solution:

  1. Preferred JavaScript code for loading / binding Win32 API
  2. CPP header file for our external dll
  3. Source CPP file for our external dll

I built a simple GUI DLL project in MSVC ++ with the later two files and compiled wmctrl.dll , depending on msvcr100.dll , and used Dependency Walker to find the "plain C" characters exported by DLLs to use js-ctypes. For example: ?wmctrl_find_window@ @ YAKPAD@Z is the "plain C" character for a C ++ api function called wmctrl_find_window .

As a warning, this code is based on temporarily changing the name of the window, which needs to be focused so that the Win32 APIs can check all the windows on the desktop to find the correct Firefox window.

You need to have access to the privileged APIs of the Mozilla platform, i.e. JavaScript inside Firefox Addon.

In your preferred JavaScript code:

 // get API constants (might already be available) const {Cc,Ci,Cu} = require("chrome"); // import js-ctypes var file=null, lib=null, ctypes = {}; Cu.import("resource://gre/modules/ctypes.jsm", ctypes); var ctypes = ctypes.ctypes; // build platform specific library path var filename = ctypes.libraryName("wmctrl"); // automatically adds '.dll' var comp = "@mozilla.org/file/directory_service;1"; var file = Cc[comp].getService(Ci.nsIProperties).get("CurProcD", Ci.nsIFile); file.append("browser_code"); // or whereever you put your DLL file.append(filename); // get the JavaScript library interface (load the library) var lib = ctypes.open(file.path); // wmctrl_find_window: returing unsigned 32bit (long) "window handle" // takes string "window title". var find_window = lib.declare( " ?wmctrl_find_window@ @ YAKPAD@Z ", /* plain "C" DLL symbol */ ctypes.stdcall_abi, ctypes.uint32_t, /* return type: uint32 */ ctypes.char.ptr); /* parameter: string */ // wmctrl_window_focus: takes unsigned 32bit (long) "window handle". var window_focus = lib.declare( " ?wmctrl_window_focus@ @ YAXK@Z ", /* plain "C" DLL symbol */ ctypes.stdcall_abi, ctypes.void_t, /* return type: void */ ctypes.uint32_t); /* parameter: uint32 */ 

wmctrldll.h

 #ifdef WMCTRLDLL_EXPORTS #define WMCTRLDLL_API __declspec(dllexport) #else #define WMCTRLDLL_API __declspec(dllimport) #endif WMCTRLDLL_API void wmctrl_window_focus (unsigned long wid); WMCTRLDLL_API unsigned long wmctrl_find_window(char* find_title); 

wmctrldll.cpp

 typedef struct { HWND hWnd; char title[255]; } myWinSpec; BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) { char String[255]; myWinSpec* to_find = (myWinSpec*) lParam; // not a window if (!hWnd) return TRUE; // not visible if (!IsWindowVisible(hWnd)) return TRUE; // no window title if (!GetWindowTextA(hWnd, (LPSTR)String, 255)) return TRUE; // no title match if (strcmp(String, to_find->title) != 0) return TRUE; to_find->hWnd = hWnd; return FALSE; } WMCTRLDLL_API void wmctrl_window_focus(unsigned long wid) { SetForegroundWindow((HWND) wid); } WMCTRLDLL_API unsigned long wmctrl_find_window(char* find_title) { myWinSpec to_find; sprintf_s(to_find.title, sizeof(to_find.title), "%s", find_title); to_find.hWnd = 0; EnumWindows(EnumWindowsProc, (LPARAM)&to_find); return (unsigned long) to_find.hWnd; } 
+1
source

Source: https://habr.com/ru/post/952705/


All Articles