diff --git a/app.go b/app.go
index 0eb4ea0..cc04e72 100644
--- a/app.go
+++ b/app.go
@@ -6,12 +6,19 @@ import (
"conjure-os/lib/provider"
"context"
"fmt"
- "github.com/wailsapp/wails/v2/pkg/runtime"
"os"
"os/exec"
+ "time"
+
+ "github.com/wailsapp/wails/v2/pkg/runtime"
)
-var games []models.Game
+var (
+ games []models.Game
+ lastEmitTimestamp = time.Now().Add(-10 * time.Second)
+ emitInterval = 300 * time.Millisecond
+ gameIsOpen = false
+)
// App struct
type App struct {
@@ -31,8 +38,27 @@ func (a *App) startup(ctx context.Context) {
provider.Update()
}
-func (a *App) onControllerChange(data any) {
- runtime.EventsEmit(a.ctx, "controller_change", data)
+func (a *App) onControllerChange(state inputs.ControllerState) {
+ now := time.Now()
+
+ if now.Sub(lastEmitTimestamp) >= emitInterval && !gameIsOpen {
+ if state.Buttons != 0 {
+ for _, button := range inputs.ConjureControllerButtons {
+ if state.Buttons&(1<
+
+
+
diff --git a/frontend/src/models/controller-state.ts b/frontend/src/models/controller-state.ts
new file mode 100644
index 0000000..441d3f4
--- /dev/null
+++ b/frontend/src/models/controller-state.ts
@@ -0,0 +1,7 @@
+export interface ControllerState {
+ joystick: {
+ x: number,
+ y: number,
+ },
+ buttons: number
+}
\ No newline at end of file
diff --git a/frontend/src/stores/app-store.ts b/frontend/src/stores/app-store.ts
index 18715bc..896d6f4 100644
--- a/frontend/src/stores/app-store.ts
+++ b/frontend/src/stores/app-store.ts
@@ -11,7 +11,8 @@ export const useAppStore = defineStore('app', {
transitionDirection: 'down' as 'up' | 'down',
selectedGame: null as Game | null,
selectedGameIndex: 0,
- qrLink: '' as string
+ qrLink: '' as string,
+ gameIsStarting: false as boolean
}),
getters: {
filteredGames(state): Game[] {
@@ -50,9 +51,11 @@ export const useAppStore = defineStore('app', {
showQr(link: string) {
this.qrLink = link;
},
- startSelectedGame() {
+ async startSelectedGame() {
if (this.selectedGame) {
- StartGame(this.selectedGame.Id).then()
+ this.gameIsStarting = true;
+ await StartGame(this.selectedGame.Id);
+ this.gameIsStarting = false;
}
else {
console.log("No game selected")
diff --git a/frontend/src/utils/key-contexts/key-context.ts b/frontend/src/utils/key-contexts/key-context.ts
index 7a4aa32..1eaffdc 100644
--- a/frontend/src/utils/key-contexts/key-context.ts
+++ b/frontend/src/utils/key-contexts/key-context.ts
@@ -1,3 +1,4 @@
+import { ControllerState } from "../../models/controller-state";
import { useAppStore } from "../../stores/app-store";
export abstract class KeyContext {
@@ -30,6 +31,31 @@ export abstract class KeyContext {
}
}
+ public handleState(state: ControllerState) {
+ if (state.joystick.x === 0) {
+ this.onKeyLeft()
+ }
+ else if (state.joystick.x === 255) {
+ this.onKeyRight()
+ }
+
+ if (state.joystick.y === 0) {
+ this.onKeyUp()
+ }
+ else if (state.joystick.y === 255) {
+ this.onKeyDown()
+ }
+
+ if ((state.buttons & 0x02) !== 0) {
+ this.onEnter()
+ }
+
+ // TODO should be 0x01 when the power button will work
+ if ((state.buttons & 0x04) !== 0) {
+ this.onEscape()
+ }
+ }
+
protected onKeyRight(): void {
console.log('onKeyRight');
}
diff --git a/frontend/src/utils/keyboard-manager.ts b/frontend/src/utils/keyboard-manager.ts
index 810b137..faf9cb7 100644
--- a/frontend/src/utils/keyboard-manager.ts
+++ b/frontend/src/utils/keyboard-manager.ts
@@ -1,3 +1,4 @@
+import { ControllerState } from "../models/controller-state";
import { CarouselKeyContext } from "./key-contexts/carousel-key-context";
import { KeyContext } from "./key-contexts/key-context";
import { SidebarKeyContext } from "./key-contexts/sidebar-key-context";
@@ -14,4 +15,8 @@ export class KeyboardManager {
static handle(event: KeyboardEvent) {
this.current?.handleKey(event);
}
+
+ static handleState(controllerState: ControllerState) {
+ this.current?.handleState(controllerState);
+ }
}
\ No newline at end of file
diff --git a/frontend/src/utils/use-keyboard-navigation.ts b/frontend/src/utils/use-keyboard-navigation.ts
index fe7f3ae..666d59f 100644
--- a/frontend/src/utils/use-keyboard-navigation.ts
+++ b/frontend/src/utils/use-keyboard-navigation.ts
@@ -4,7 +4,7 @@ import { EventsOn } from "../../wailsjs/runtime";
export function useKeyboardNavigation(): void {
onMounted(() => {
- EventsOn("controller_change", (data) => console.log(data));
+ EventsOn("controller_change", KeyboardManager.handleState.bind(KeyboardManager));
window.addEventListener('keydown', KeyboardManager.handle.bind(KeyboardManager));
});
diff --git a/frontend/wailsjs/runtime/runtime.d.ts b/frontend/wailsjs/runtime/runtime.d.ts
index 94778df..4445dac 100644
--- a/frontend/wailsjs/runtime/runtime.d.ts
+++ b/frontend/wailsjs/runtime/runtime.d.ts
@@ -134,7 +134,7 @@ export function WindowIsFullscreen(): Promise;
// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize)
// Sets the width and height of the window.
-export function WindowSetSize(width: number, height: number): Promise;
+export function WindowSetSize(width: number, height: number): void;
// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize)
// Gets the width and height of the window.
diff --git a/go.mod b/go.mod
index a42c190..aa26443 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@ toolchain go1.23.5
require (
github.com/karalabe/hid v1.0.0
- github.com/wailsapp/wails/v2 v2.9.2
+ github.com/wailsapp/wails/v2 v2.10.1
gopkg.in/yaml.v3 v3.0.1
)
diff --git a/go.sum b/go.sum
index 9690a5f..58e26dc 100644
--- a/go.sum
+++ b/go.sum
@@ -69,8 +69,8 @@ github.com/wailsapp/go-webview2 v1.0.19 h1:7U3QcDj1PrBPaxJNCui2k1SkWml+Q5kvFUFyT
github.com/wailsapp/go-webview2 v1.0.19/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
-github.com/wailsapp/wails/v2 v2.9.2 h1:Xb5YRTos1w5N7DTMyYegWaGukCP2fIaX9WF21kPPF2k=
-github.com/wailsapp/wails/v2 v2.9.2/go.mod h1:uehvlCwJSFcBq7rMCGfk4rxca67QQGsbg5Nm4m9UnBs=
+github.com/wailsapp/wails/v2 v2.10.1 h1:QWHvWMXII2nI/nXz77gpPG8P3ehl6zKe+u4su5BWIns=
+github.com/wailsapp/wails/v2 v2.10.1/go.mod h1:zrebnFV6MQf9kx8HI4iAv63vsR5v67oS7GTEZ7Pz1TY=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
diff --git a/lib/inputs/joystick.go b/lib/inputs/joystick.go
index d73c8d4..375e3dc 100644
--- a/lib/inputs/joystick.go
+++ b/lib/inputs/joystick.go
@@ -23,52 +23,60 @@ type Controller struct {
Device *hid.Device
}
-func (c *Controller) ReadState() error {
- buf := make([]byte, 64)
+func (c *Controller) ReadState(buf []byte) (*ControllerState, error) {
_, err := c.Device.Read(buf)
+
if err != nil {
- return err
+ return nil, err
}
- fmt.Printf("Joystick: X=%d Y=%d Buttons=%08b\n", buf[0], buf[1], buf[6])
- return nil
+ x := buf[0] // Horizontal axis (0–255)
+ y := buf[1] // Vertical axis (0–255)
+ buttons := buf[6] // Buttons as bitfield
+ state := ControllerState{
+ Joystick: Vec2B{x, y},
+ Buttons: buttons,
+ }
+
+ return &state, nil
}
type Vec2B struct {
- X, Y byte
+ X byte `json:"x"`
+ Y byte `json:"y"`
}
type ControllerState struct {
- joystick Vec2B
- buttons byte
+ Joystick Vec2B `json:"joystick"`
+ Buttons byte `json:"buttons"`
}
type ConjureControllerButton int
const (
- ButtonA ConjureControllerButton = iota //0
- ButtonB
- ButtonC
+ ButtonPower ConjureControllerButton = iota //0
+ ButtonStart
Button1
Button2
Button3
- ButtonStart
- ButtonPower // 7
+ ButtonA
+ ButtonB
+ ButtonC // 7
)
var ConjureControllerButtons = []ConjureControllerButton{
- ButtonA,
- ButtonB,
- ButtonC,
+ ButtonStart,
+ ButtonPower,
Button1,
Button2,
Button3,
- ButtonStart,
- ButtonPower,
+ ButtonA,
+ ButtonB,
+ ButtonC,
}
func (s ConjureControllerButton) String() string {
@@ -94,7 +102,7 @@ func (s ConjureControllerButton) String() string {
}
}
-func Start(onStateChange func(any)) {
+func Start(onStateChange func(ControllerState)) {
fmt.Println("Opening devices")
const vendorID = 0x0079
const productID = 0x0006
@@ -111,50 +119,34 @@ func Start(onStateChange func(any)) {
}
// Open the first matching device
- device, err := devices[0].Open()
- if err != nil {
- fmt.Printf("Failed to open device: %v", err)
- return
- }
- defer device.Close()
- fmt.Println("Reading data... Press Ctrl+C to exit")
+ for i, deviceDetected := range devices {
- buf := make([]byte, 32) // Adjust size if needed
- for {
- _, err := device.Read(buf)
+ fmt.Printf("device %d detected\n", i)
+ device, err := deviceDetected.Open()
if err != nil {
- fmt.Printf("Read error: %v", err)
+ fmt.Printf("Failed to open device: %v", err)
return
}
+ defer device.Close()
- // For debugging: print raw data
- // fmt.Printf("Raw: % X\n", buf[:n])
+ controller := Controller{Device: device}
- // Example: decode joystick + button state
- x := buf[0] // Horizontal axis (0–255)
- y := buf[1] // Vertical axis (0–255)
- buttons := buf[6] // Buttons as bitfield
- state := ControllerState{
- joystick: Vec2B{x, y},
- buttons: buttons,
- }
+ fmt.Println("Reading data... Press Ctrl+C to exit")
- // fmt.Printf("Joystick X: %d, Y: %d, Buttons: %08b\n", x, y, buttons)
+ buf := make([]byte, 32) // Adjust size if needed
+ for {
+ state, err := controller.ReadState(buf)
- if buttons != 0 {
- for _, button := range ConjureControllerButtons {
- if buttons&(1<