Adobe-Runtime-Support icon indicating copy to clipboard operation
Adobe-Runtime-Support copied to clipboard

[Feature Request] Getting NativeWindow handle (HWND)

Open itlancer opened this issue 5 years ago • 25 comments

Feature Description

Getting NativeWindow handle (HWND) necessary to windows management and extend AIR functionality by native extensions for desktop platforms. With Windows platform it HWND. With other desktop platforms it could be different like Electron uses: https://www.electronjs.org/docs/api/browser-window#wingetnativewindowhandle

Many native operations with windows requires handles/descriptors to use. Such getter would be very useful for AIR developers.

Related issues: https://tracker.adobe.com/#/view/AIR-3962230 https://github.com/Gamua/Adobe-Runtime-Support/issues/210

Known Workarounds

Write native extension with enumerating windows to find your AIR window. Or use NativeProcess to call separate application or utility script that make something like that. Both of that approaches slow and not stable in some cases.

itlancer avatar Feb 21 '20 20:02 itlancer

This is quite easy with a native extension, what exactly is the use case in AIR directly?

marchbold avatar Feb 22 '20 01:02 marchbold

It's pretty easy with one AIR window but no so elegant when you working with multiple AIR windows which could be created/closed at runtime. I have done it by window title searching. Also it can be done with checking window coordinates and may be some other not unique parameters. Getting HWND directly from NativeWindow could be more correctly way to do that. My case need such solution because of these points:

  • Changing window styles properties dynamically at runtime (GWL_STYLE, GWL_EXSTYLE etc).
  • Interact between non-AIR windows too. Order management etc.
  • Working with Windows Messages queue (https://docs.microsoft.com/en-us/windows/win32/learnwin32/window-messages). Receive/dispatch events that cannot be handled via AIR directly.

itlancer avatar Feb 22 '20 09:02 itlancer

So presumably this is just for a handle you’d use from within a native extension, maybe it could be a method added to the FRE... set of APIs called from the native layer?

ajwfrost avatar Feb 22 '20 10:02 ajwfrost

@ajwfrost For example, I have 2 different AS3/AIR windows (NativeWindow). I need to know handles for both of them. Not an array of all AIR process windows handles but "NativeWindow A - has handle 1234", "NativeWindow B - has handle 5678" etc. There are two approaches for my opinion:

  1. Create new AS3 NativeWindow::nativeHandle getter property (or some different naming). Then we can use that handle to pass it to native extension and use there. But it could be complex for non-Windows platfroms where handle not just "number".
  2. Create FRE functions/APIs to get AIR windows handles. But there need somehow to distinguish windows from each other. May be it could be objects with title/coordinates. May be there could be new FRE function that can get window handle from specified AS3/AIR NativeWindow. From AS3/AIR side we can pass NativeWindow instance by ExtensionContext::call and with native extension method do something like that (Windows extension code draft):
//Some native extension method
FREObject passWindow(FREContext ctx, void* funcData, uint32_t argc, FREObject argv[]) {
	HWND windowHWND;
	FREGetObjectAsWindowHandle(argv[0], &windowHWND);//Some "new" function to get NativeWindow handle
	
	//use windowHWND here

	return NULL;
}

Second approach would be perfect for any of platforms and any cases.

itlancer avatar Feb 22 '20 10:02 itlancer

Ah yeah I understand the use case with regards multiple windows.

You would probably need a way to commonly identify the windows between the AS3 and native layers so would have to be more than just a FRE function, or at least some common identifier added to both layers?

marchbold avatar Feb 23 '20 08:02 marchbold

@marchbold Yes, I tried to suggest approaches in comment above with AS3 getter method (window identifier) and another way to get such identifier/link via FRE function from passed AS3 NativeWindow object to native layer via ExtensionContext::call.

itlancer avatar Feb 23 '20 10:02 itlancer

Passing the NativeWindow object in to the ANE function makes the most sense to me, we can check the code but I can’t imagine it will be that difficult to return an appropriate handle for Windows/MacOS..

ajwfrost avatar Feb 23 '20 14:02 ajwfrost

I need this feature too.

pol2095 avatar Feb 24 '21 21:02 pol2095

We @Dallmeier-electronic would also like to have this feature for window identification. Currently, an external (display) service is doing this but it would be better if our application could provide this information on its own. We need this for z-sorting / arranging windows in the proper order. Our GUI is running in transparent mode with cut-out parts (BlendMode.ERASE) and reveals other application(s) (video) in the background.

2jfw avatar Feb 25 '21 09:02 2jfw

Hi

Thanks for the reminder on this one, we have just been discussing it and looking into it a little. I think the danger is that providing the native window handle is something that could then cause problems if something then happened within the runtime that caused the handle to invalidate (i.e. if the window was closed...). So it's only "safe" if it's used in one thread at one time .. which is also the pattern Adobe took with the access of BitmapData and ByteArray objects. So if you're happy with this restriction, we could add two functions:

FREResult FREAcquireNativeWindowHandle(FREObject nativeWindow, FRENativeWindow* handle);
FREResult FREReleaseNativeWindowHandle(FREObject nativeWindow);

And then you would need to acquire the native handle, use it in your ANE function, and release it again. The 'handle' type would then be platform-specific, e.g. HWND, NSWindow*, GtkWidget*

If that sounds okay, we can start looking at what's needed to actually implement this and roll out the new ANE headers/libraries.. I'm thinking this would be a desktop-only feature but if anyone sees this as necessary on Android/iOS please let me know!

thanks

ajwfrost avatar Feb 25 '21 09:02 ajwfrost

@ajwfrost: Could you make the Process ID of a Native Window accessible at runtime?

2jfw avatar Feb 25 '21 11:02 2jfw

@2jfw all the windows would be running in the same process so if you want the OS process ID, you can just use normal functions like GetCurrentProcessId() (for Win32) or getpid()? or am I misunderstanding what you're after here..

ajwfrost avatar Feb 25 '21 11:02 ajwfrost

@ajwfrost As far as I know, each window has its own ProcessID. In our scenario a custom service gets the title of the NativeWindow and determines the processID and thus the related window handle to be able to change the z-order of the NativeWindow.

EDIT: It is a multi window application so I assume that by the unique title of each AIR native window the handle can be determined. I will add more details when I will receive an answer from the backend service team regarding what they currently do to get the window handle by the native window title

EDIT2: Sorry for the confusion - the service uses FindWindowW (https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-findwindoww) and retrieves the HWND, so there is no ID involved.

2jfw avatar Feb 25 '21 12:02 2jfw

For Windows a property in NativeWindow like this : var processId:int = stage.nativeWindow.processId;

and to use it in the extension : IntPtr^ m_hwnd = IntPtr(processId);

pol2095 avatar Feb 25 '21 12:02 pol2095

@pol2095 that might be fine for Windows where everything is done through essentially a 'safe' pointer i.e. HWND type .. but on other platforms, what happens if we provide a pointer, and this is then used in a function call after it's been destroyed? hence the idea of Acquire/Release within an extension (you really shouldn't need this value within any ActionScript code!!)

thanks

ajwfrost avatar Feb 25 '21 14:02 ajwfrost

@ajwfrost, let it be as described at https://github.com/Gamua/Adobe-Runtime-Support/issues/236#issuecomment-785772231 or https://github.com/Gamua/Adobe-Runtime-Support/issues/236#issuecomment-589941885 to work with NativeWindow handlers only at native side.

itlancer avatar Feb 25 '21 16:02 itlancer

Any news about HWND, please get the HWND in as3 only for Windows, it's easier to implement. On Mac it's possible to get the window, iOS and Android not necessary for now.

pol2095 avatar Sep 06 '21 07:09 pol2095

Hi - actually, we had implemented this, it's just waiting in a 'next' feature branch where a bunch of API updates will be happening and where we'll need to therefore change the namespaces and version number away from "33.1". In discussion with Adobe they'd suggested we skip some numbers to avoid confusion with the Flash Player in China (currently at version 34 I think!) so we're going to bump it to version 50 which is also the version number that we use for Flash Player enterprise support ourselves.

So once we've got the iOS15 support done with the current 33.1 branch at the end of this month, we'll push out a beta for this as version 50.0....

thanks

ajwfrost avatar Sep 06 '21 08:09 ajwfrost

Any news ?

pol2095 avatar Dec 13 '21 07:12 pol2095

Yes we ended up with a lot more to do on the 33.1 branch than we had thought :-( We have one more release on that about to land and then we'll try to get everything sorted out for a 50.0 beta. Sorry for the delays...

ajwfrost avatar Dec 13 '21 09:12 ajwfrost

I see AIR 50.0.0.1 BETA, does it support this feature and how to use it on Windows ?

pol2095 avatar Sep 19 '22 17:09 pol2095

It should do but for a bug it seems... will get someone to check that out and do a quick sample..

ajwfrost avatar Sep 20 '22 11:09 ajwfrost

Okay so there does seem to be an issue with the library not being updated .. which means it's not possible to do this currently, but will be fixed in the proper release. You can then do e.g.

  var b : Boolean = extCtx.call("TestFunction", 12, stage.nativeWindow) as Boolean;

in ActionScript and handle it in C++

	HWND hWnd = NULL;
	FREResult res = FREAcquireNativeWindowHandle(argv[1], &hWnd);
	if (res == FRE_OK)
	{
		::SetWindowPos(hWnd, NULL, value, value, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
		FREReleaseNativeWindowHandle(argv[1]);
	}

ajwfrost avatar Sep 22 '22 13:09 ajwfrost

Thanks, this line is necessary ? ::SetWindowPos(hWnd, NULL, value, value, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);

and what is-it value ?

pol2095 avatar Sep 23 '22 08:09 pol2095

Sorry, no that was just an illustration of how you can then use the window handle... so our test case just took a value (also passed from AS code) and then moved the window to that location (both x and y values).

We've apparently got some tweaks to make to the other platforms too..

ajwfrost avatar Sep 23 '22 09:09 ajwfrost

Thanks, it work now.

pol2095 avatar Oct 17 '22 21:10 pol2095

This feature now available with AIR 50 for desktop platforms. Thanks!

Note: To use it with Windows you need to include <windows.h> before FlashRuntimeExtensions.h in your native extension:

#include <windows.h>
#include "FlashRuntimeExtensions.h"

To use it with Linux you need to include <gtk/gtk.h> before FlashRuntimeExtensions.h in your native extension:

#include <gtk/gtk.h>
#include "FlashRuntimeExtensions.h"

To use it with macOS you need to include <Cocoa/Cocoa.h> before <Adobe AIR/FlashRuntimeExtensions.h> in your native extension:

#include <Cocoa/Cocoa.h>
#include <Adobe AIR/FlashRuntimeExtensions.h>

Related issue: https://github.com/airsdk/Adobe-Runtime-Support/issues/2311

itlancer avatar Feb 15 '23 09:02 itlancer