aboutsummaryrefslogtreecommitdiff
path: root/src/desktopMain/kotlin/moe.yuuta.desktop/Desktop.kt
blob: b52680e1862fca34520b13e80f5606a7403eec9a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package moe.yuuta.desktop

import kotlinx.cinterop.*
import libui.ktx.MsgBoxError
import libui.ktx.appWindow
import libui.ktx.hbox
import libui.ktx.tableview
import platform.windows.*

const val FLAG = DESKTOP_READOBJECTS or
        DESKTOP_CREATEWINDOW or
        DESKTOP_CREATEMENU or
        DESKTOP_HOOKCONTROL or
        DESKTOP_JOURNALRECORD or
        DESKTOP_JOURNALPLAYBACK or
        DESKTOP_ENUMERATE or
        DESKTOP_WRITEOBJECTS or
        DESKTOP_SWITCHDESKTOP

private val mDesktops = mutableListOf<String>()

@Suppress("unused")
fun main(args: Array<String>?) {
    try {
        appMain()
    } catch (e: Throwable) {
        MessageBoxA(null,
            "App crashed unexpectedly.\n" +
                    "Exception: $e\n" +
                    "System error code: ${GetLastError()}",
            "Secure Desktop",
            (MB_OK or MB_ICONERROR).convert())
    }
}

fun appMain() = appWindow(
    title = "Desktops",
    width = 320,
    height = 100
) {
    refresh()
    if (!mDesktops.contains("CustomDesktop")) {
        WinApi.create("CustomDesktop", FLAG)
        mDesktops.add("CustomDesktop")
    }
    hbox {
        tableview(mDesktops) {
            column("Name") {
                label {
                    data[it]
                }
            }
            column("Action") {
                button("Switch to") {
                    val desk = WinApi.open(FLAG, data[it])
                    if (desk == null) {
                        MsgBoxError("Cannot open the desktop",
                            "The system returns an empty desktop.\n" +
                                    "Error: ${GetLastError()}")
                        return@button
                    }
                    // TODO: Run an instance in a desktop only
                    val pathBuffer = nativeHeap.allocArray<CHARVar>(MAX_PATH)
                    GetModuleFileNameA(null, pathBuffer, MAX_PATH)
                    val path = pathBuffer.toKString()
                    nativeHeap.free(pathBuffer)
                    WinApi.run(path, data[it])
                    if (!WinApi.switch(desk)) {
                        MsgBoxError("Cannot switch to the desktop",
                            "The system reports this operation fails.\n" +
                                    "Error: ${GetLastError()}")
                        return@button
                    }
                }
            }
        }
        // TODO: Support creating new desktops
    }
}

private fun refresh() {
    mDesktops.clear()
    if (EnumDesktopsA(GetProcessWindowStation(),
            staticCFunction { lpszDesktop, _ ->
                if (lpszDesktop == null) return@staticCFunction 1
                mDesktops.add(lpszDesktop.toKString())
                return@staticCFunction 1
            },
            0) == 0) {
        MsgBoxError("Cannot obtain the desktop list",
            "Error code: ${GetLastError()}")
    }
}