cleaning up desktop interactions. need to move things into individual files

This commit is contained in:
dtookey 2023-08-08 09:01:47 -04:00
parent 5bf0e4c226
commit 1cb68f19a7
2 changed files with 158 additions and 8 deletions

View File

@ -84,14 +84,149 @@ interface DesktopController {
}
}
class WindowsDesktopController : DesktopController {
interface OSProxy{
fun getActiveWindowName(): String
}
/**
* Windows implementation of [DesktopController].
*
* This class provides methods to interact with the desktop on Windows
* by calling Win32 APIs.
*
* It implements the [DesktopController] interface to provide desktop
* functionality like getting the mouse pointer location on Windows.
*/
class WindowsDesktopController : DesktopController, OSProxy {
companion object{
/**
* Converts a native byte buffer to a String.
*
* This takes a byte array [byteBuffer] containing text from a native Win32 call,
* converts it to a String using JNA, and trims whitespace characters.
*
* Usage example:
*
* ```
* val buffer = ByteArray(256)
* GetWindowTextA(hwnd, buffer, buffer.size) // Win32 call
*
* val windowTitle = nativeByteBufferToString(buffer)
* println(windowTitle) // Print title string
* ```
*
* @param byteBuffer Byte array containing text from a native call
* @return The native text as a String
*/
private fun nativeByteBufferToString(byteBuffer: ByteArray): String{
// I guess this prunes anything that isn't on the ascii table?
val wText = Native.toString(byteBuffer).trim { it <= ' ' }
return wText
}
}
/**
* Interface for calling Windows User32 API functions.
*
* This defines an interface extending StdCallLibrary to call native
* Windows User32 library functions like EnumWindows, GetWindowTextA etc.
*
* Classes can implement this interface to make direct calls to the
* User32 DLL on Windows.
*/
internal interface User32 : StdCallLibrary {
/**
* Interface for a Windows callback function to enumerate windows.
*
* This extends the StdCallLibrary.StdCallCallback to define a callback
* method that will be invoked by the Windows API EnumWindows function.
*
* The callback method accepts a window handle (HWND) and a user-defined
* pointer, and returns a Boolean indicating whether to continue enumeration.
*
* Usage example:
* ```
* val callback = object : WNDENUMPROC {
* override fun callback(hWnd: Pointer?, arg: Pointer?): Boolean {
* // Check if hWnd matches target window
* if (matchesTarget(hWnd)) {
* // Found target window, stop enumeration
* return false
* }
* // Keep enumerating
* return true
* }
* }
* ```
*
* @param hWnd Window handle (HWND) for the current enumerated window.
* @param arg User-defined data pointer passed to EnumWindows.
* @return True to continue enumerating windows, false to stop.
*/
interface WNDENUMPROC : StdCallLibrary.StdCallCallback {
fun callback(hWnd: Pointer?, arg: Pointer?): Boolean
}
/**
* Enumerates windows on the system.
*
* This calls the Windows API EnumWindows function to enumerate all top-level windows.
*
* For each window, it calls the provided [WNDENUMPROC] callback function,
* passing the window handle [hWnd] and user-defined [userData] pointer.
*
* Enumeration can be stopped by returning false from the callback.
*
* Usage example:
*
* ```
* val windows = mutableListOf<HWND>()
*
* val callback = object : WNDENUMPROC {
* override fun callback(hWnd: Pointer?, arg: Pointer?): Boolean {
* windows.add(hWnd) // Add hWnd to list
* return true // Continue enumerating
* }
* }
*
* EnumWindows(callback, null) // Get all top-level windows
*
* println(windows) // Print list of HWNDs
* ```
*
* @param lpEnumFunc The [WNDENUMPROC] callback to call for each window.
* @param userData Optional user-defined data to pass to the callback.
* @return True if successful, false otherwise.
*/
fun EnumWindows(lpEnumFunc: WNDENUMPROC?, userData: Pointer?): Boolean
/**
* Gets the title text of the specified window.
*
* This calls the Win32 API GetWindowTextA function to get the title
* text for the window handle [hWnd].
*
* The window text is copied into the [lpString] buffer up to [nMaxCount] characters.
*
* Usage example:
*
* ```
* val buffer = ByteArray(256)
* val hwnd = getWindowHandle() // get some HWND
*
* GetWindowTextA(hwnd, buffer, buffer.size)
*
* val windowTitle = String(buffer)
* println(windowTitle)
* ```
*
* @param hWnd The window handle (HWND).
* @param lpString The buffer to receive the window text.
* @param nMaxCount The maximum number of characters to copy to the buffer.
* @return The length of the window text (excluding null-terminator).
*/
fun GetWindowTextA(hWnd: Pointer?, lpString: ByteArray?, nMaxCount: Int): Int
fun GetForegroundWindow(): Pointer?
@ -103,13 +238,28 @@ class WindowsDesktopController : DesktopController {
}
fun getCurrentlyActiveWindowName(): String {
/**
* Gets the title of the active/foreground window.
*
* This calls Win32 APIs to get the handle of the foreground window,
* then gets its title text.
*
* Usage example:
*
* ```
* val activeWindowName = getActiveWindowName()
*
* println(activeWindowName) // Prints foreground window title
* ```
*
* @return The title text of the current foreground window.
*/
override fun getActiveWindowName(): String {
val user32 = User32.INSTANCE
val textBuffer = ByteArray(512)
val windowText = ByteArray(512)
val hWnd = user32.GetForegroundWindow()
user32.GetWindowTextA(hWnd, windowText, 512)
val wText = Native.toString(windowText).trim { it <= ' ' } //i have no idea what this does
return wText
user32.GetWindowTextA(user32.GetForegroundWindow(), textBuffer, 512)
return nativeByteBufferToString(textBuffer)
}
}

View File

@ -64,6 +64,6 @@ class DesktopControllerTest {
@Test
fun devTest(){
val c = WindowsDesktopController()
println("TEXT: ${ c.getCurrentlyActiveWindowName()}")
println("TEXT: ${ c.getActiveWindowName()}")
}
}