improve(webkit): debounce keyboard events and add rendering backend detection
- commit
- 18292b32e3a239d70071d8d638faa575444d41ec
- author
- bamen · · 2025-09-16 19:00 UTC
- committer
- bamen · · 2025-09-16 21:07 UTC
- parent
- eac22c5
- signature
- unsigned
1 file · +67 -2
M pkg/webkit/keyboard_cgo.go +67 -2
| @@ -78,8 +78,10 @@ static void attach_mouse_legacy(GtkWidget* widget, unsigned long id) { | |||
| 78 | 78 | import "C" | |
| 79 | 79 | ||
| 80 | 80 | import ( | |
| 81 | + | "encoding/json" | |
| 81 | 82 | "fmt" | |
| 82 | 83 | "log" | |
| 84 | + | "strings" | |
| 83 | 85 | "sync" | |
| 84 | 86 | "sync/atomic" | |
| 85 | 87 | "time" | |
| @@ -149,10 +151,11 @@ func dispatchAccelerator(uid uintptr, keyval uint, state uint) { | |||
| 149 | 151 | shift := (state & uint(C.GDK_SHIFT_MASK)) != 0 | |
| 150 | 152 | // Map keyval to string names | |
| 151 | 153 | var keyName string | |
| 154 | + | logMinusEvent := false | |
| 152 | 155 | switch keyval { | |
| 153 | 156 | case uint(C.GDK_KEY_minus), uint(C.GDK_KEY_KP_Subtract), uint(C.GDK_KEY_underscore): | |
| 154 | 157 | // Normalize minus; log raw detection for diagnostics | |
| 155 | - | log.Printf("[accelerator-raw] minus key detected ctrl=%v alt=%v keyval=0x%x", ctrl, alt, keyval) | |
| 158 | + | logMinusEvent = true | |
| 156 | 159 | keyName = "-" | |
| 157 | 160 | case uint(C.GDK_KEY_equal), uint(C.GDK_KEY_KP_Add): | |
| 158 | 161 | keyName = "=" | |
| @@ -182,6 +185,16 @@ func dispatchAccelerator(uid uintptr, keyval uint, state uint) { | |||
| 182 | 185 | return | |
| 183 | 186 | } | |
| 184 | 187 | ||
| 188 | + | now := time.Now() | |
| 189 | + | rawKey := fmt.Sprintf("raw:%v:%v:%v:%s", ctrl, alt, shift, keyName) | |
| 190 | + | if shouldDebounceShortcut(uid, rawKey, now) { | |
| 191 | + | return | |
| 192 | + | } | |
| 193 | + | ||
| 194 | + | if logMinusEvent { | |
| 195 | + | log.Printf("[accelerator-raw] minus key detected ctrl=%v alt=%v keyval=0x%x", ctrl, alt, keyval) | |
| 196 | + | } | |
| 197 | + | ||
| 185 | 198 | // Candidate accelerator strings in order | |
| 186 | 199 | candidates := []string{keyName} | |
| 187 | 200 | if ctrl && shift { | |
| @@ -211,7 +224,6 @@ func dispatchAccelerator(uid uintptr, keyval uint, state uint) { | |||
| 211 | 224 | normalized = "" | |
| 212 | 225 | } | |
| 213 | 226 | ||
| 214 | - | now := time.Now() | |
| 215 | 227 | // Forward normalized shortcut to GUI KeyboardService via DOM event if present | |
| 216 | 228 | if normalized != "" && !shouldDebounceShortcut(uid, "dom:"+normalized, now) { | |
| 217 | 229 | regMu.RLock() | |
| @@ -369,6 +381,12 @@ func goOnUcmMessage(id C.ulong, json *C.char) { | |||
| 369 | 381 | return | |
| 370 | 382 | } | |
| 371 | 383 | goPayload := C.GoString(json) | |
| 384 | + | ||
| 385 | + | // Handle rendering backend detection messages specially | |
| 386 | + | if handleRenderingBackendMessage(goPayload) { | |
| 387 | + | return | |
| 388 | + | } | |
| 389 | + | ||
| 372 | 390 | vw.dispatchScriptMessage(goPayload) | |
| 373 | 391 | } | |
| 374 | 392 | ||
| @@ -422,3 +440,50 @@ func goQuitMainLoop() { | |||
| 422 | 440 | log.Printf("[webkit] Window close requested - quitting main loop") | |
| 423 | 441 | QuitMainLoop() | |
| 424 | 442 | } | |
| 443 | + | ||
| 444 | + | // handleRenderingBackendMessage processes rendering backend detection messages | |
| 445 | + | func handleRenderingBackendMessage(payload string) bool { | |
| 446 | + | // Parse JSON to check if this is a rendering backend detection message | |
| 447 | + | if !strings.Contains(payload, "rendering_backend_detection") { | |
| 448 | + | return false | |
| 449 | + | } | |
| 450 | + | ||
| 451 | + | // Simple JSON parsing for the specific structure we expect | |
| 452 | + | // {"type":"rendering_backend_detection","data":{...}} | |
| 453 | + | var msg struct { | |
| 454 | + | Type string `json:"type"` | |
| 455 | + | Data struct { | |
| 456 | + | WebGLAvailable bool `json:"webgl_available"` | |
| 457 | + | Renderer string `json:"renderer"` | |
| 458 | + | Vendor string `json:"vendor"` | |
| 459 | + | Version string `json:"version"` | |
| 460 | + | ShadingLanguageVersion string `json:"shading_language_version"` | |
| 461 | + | MaxTextureSize int `json:"max_texture_size"` | |
| 462 | + | HardwareAccelerated bool `json:"hardware_accelerated"` | |
| 463 | + | } `json:"data"` | |
| 464 | + | } | |
| 465 | + | ||
| 466 | + | if err := json.Unmarshal([]byte(payload), &msg); err != nil { | |
| 467 | + | log.Printf("[webkit] Failed to parse rendering backend message: %v", err) | |
| 468 | + | return false | |
| 469 | + | } | |
| 470 | + | ||
| 471 | + | if msg.Type != "rendering_backend_detection" { | |
| 472 | + | return false | |
| 473 | + | } | |
| 474 | + | ||
| 475 | + | // Log the detected rendering backend information | |
| 476 | + | backendType := "SOFTWARE" | |
| 477 | + | if msg.Data.HardwareAccelerated { | |
| 478 | + | backendType = "HARDWARE" | |
| 479 | + | } | |
| 480 | + | ||
| 481 | + | log.Printf("[webkit] Detected rendering backend: %s", backendType) | |
| 482 | + | log.Printf("[webkit] WebGL available: %v", msg.Data.WebGLAvailable) | |
| 483 | + | log.Printf("[webkit] Renderer: %s", msg.Data.Renderer) | |
| 484 | + | log.Printf("[webkit] Vendor: %s", msg.Data.Vendor) | |
| 485 | + | log.Printf("[webkit] Version: %s", msg.Data.Version) | |
| 486 | + | log.Printf("[webkit] Max texture size: %d", msg.Data.MaxTextureSize) | |
| 487 | + | ||
| 488 | + | return true | |
| 489 | + | } | |
| @@ -78,8 +78,10 @@ static void attach_mouse_legacy(GtkWidget* widget, unsigned long id) { | |||||
| 78 | import "C" | 78 | import "C" | ||
| 79 | 79 | ||||
| 80 | import ( | 80 | import ( | ||
| 81 | + | "encoding/json" | |||
| 81 | "fmt" | 82 | "fmt" | ||
| 82 | "log" | 83 | "log" | ||
| 84 | + | "strings" | |||
| 83 | "sync" | 85 | "sync" | ||
| 84 | "sync/atomic" | 86 | "sync/atomic" | ||
| 85 | "time" | 87 | "time" | ||
| @@ -149,10 +151,11 @@ func dispatchAccelerator(uid uintptr, keyval uint, state uint) { | |||||
| 149 | shift := (state & uint(C.GDK_SHIFT_MASK)) != 0 | 151 | shift := (state & uint(C.GDK_SHIFT_MASK)) != 0 | ||
| 150 | // Map keyval to string names | 152 | // Map keyval to string names | ||
| 151 | var keyName string | 153 | var keyName string | ||
| 154 | + | logMinusEvent := false | |||
| 152 | switch keyval { | 155 | switch keyval { | ||
| 153 | case uint(C.GDK_KEY_minus), uint(C.GDK_KEY_KP_Subtract), uint(C.GDK_KEY_underscore): | 156 | case uint(C.GDK_KEY_minus), uint(C.GDK_KEY_KP_Subtract), uint(C.GDK_KEY_underscore): | ||
| 154 | // Normalize minus; log raw detection for diagnostics | 157 | // Normalize minus; log raw detection for diagnostics | ||
| 155 | - | log.Printf("[accelerator-raw] minus key detected ctrl=%v alt=%v keyval=0x%x", ctrl, alt, keyval) | 158 | + | logMinusEvent = true |
| 156 | keyName = "-" | 159 | keyName = "-" | ||
| 157 | case uint(C.GDK_KEY_equal), uint(C.GDK_KEY_KP_Add): | 160 | case uint(C.GDK_KEY_equal), uint(C.GDK_KEY_KP_Add): | ||
| 158 | keyName = "=" | 161 | keyName = "=" | ||
| @@ -182,6 +185,16 @@ func dispatchAccelerator(uid uintptr, keyval uint, state uint) { | |||||
| 182 | return | 185 | return | ||
| 183 | } | 186 | } | ||
| 184 | 187 | ||||
| 188 | + | now := time.Now() | |||
| 189 | + | rawKey := fmt.Sprintf("raw:%v:%v:%v:%s", ctrl, alt, shift, keyName) | |||
| 190 | + | if shouldDebounceShortcut(uid, rawKey, now) { | |||
| 191 | + | return | |||
| 192 | + | } | |||
| 193 | + | ||||
| 194 | + | if logMinusEvent { | |||
| 195 | + | log.Printf("[accelerator-raw] minus key detected ctrl=%v alt=%v keyval=0x%x", ctrl, alt, keyval) | |||
| 196 | + | } | |||
| 197 | + | ||||
| 185 | // Candidate accelerator strings in order | 198 | // Candidate accelerator strings in order | ||
| 186 | candidates := []string{keyName} | 199 | candidates := []string{keyName} | ||
| 187 | if ctrl && shift { | 200 | if ctrl && shift { | ||
| @@ -211,7 +224,6 @@ func dispatchAccelerator(uid uintptr, keyval uint, state uint) { | |||||
| 211 | normalized = "" | 224 | normalized = "" | ||
| 212 | } | 225 | } | ||
| 213 | 226 | ||||
| 214 | - | now := time.Now() | |||
| 215 | // Forward normalized shortcut to GUI KeyboardService via DOM event if present | 227 | // Forward normalized shortcut to GUI KeyboardService via DOM event if present | ||
| 216 | if normalized != "" && !shouldDebounceShortcut(uid, "dom:"+normalized, now) { | 228 | if normalized != "" && !shouldDebounceShortcut(uid, "dom:"+normalized, now) { | ||
| 217 | regMu.RLock() | 229 | regMu.RLock() | ||
| @@ -369,6 +381,12 @@ func goOnUcmMessage(id C.ulong, json *C.char) { | |||||
| 369 | return | 381 | return | ||
| 370 | } | 382 | } | ||
| 371 | goPayload := C.GoString(json) | 383 | goPayload := C.GoString(json) | ||
| 384 | + | ||||
| 385 | + | // Handle rendering backend detection messages specially | |||
| 386 | + | if handleRenderingBackendMessage(goPayload) { | |||
| 387 | + | return | |||
| 388 | + | } | |||
| 389 | + | ||||
| 372 | vw.dispatchScriptMessage(goPayload) | 390 | vw.dispatchScriptMessage(goPayload) | ||
| 373 | } | 391 | } | ||
| 374 | 392 | ||||
| @@ -422,3 +440,50 @@ func goQuitMainLoop() { | |||||
| 422 | log.Printf("[webkit] Window close requested - quitting main loop") | 440 | log.Printf("[webkit] Window close requested - quitting main loop") | ||
| 423 | QuitMainLoop() | 441 | QuitMainLoop() | ||
| 424 | } | 442 | } | ||
| 443 | + | ||||
| 444 | + | // handleRenderingBackendMessage processes rendering backend detection messages | |||
| 445 | + | func handleRenderingBackendMessage(payload string) bool { | |||
| 446 | + | // Parse JSON to check if this is a rendering backend detection message | |||
| 447 | + | if !strings.Contains(payload, "rendering_backend_detection") { | |||
| 448 | + | return false | |||
| 449 | + | } | |||
| 450 | + | ||||
| 451 | + | // Simple JSON parsing for the specific structure we expect | |||
| 452 | + | // {"type":"rendering_backend_detection","data":{...}} | |||
| 453 | + | var msg struct { | |||
| 454 | + | Type string `json:"type"` | |||
| 455 | + | Data struct { | |||
| 456 | + | WebGLAvailable bool `json:"webgl_available"` | |||
| 457 | + | Renderer string `json:"renderer"` | |||
| 458 | + | Vendor string `json:"vendor"` | |||
| 459 | + | Version string `json:"version"` | |||
| 460 | + | ShadingLanguageVersion string `json:"shading_language_version"` | |||
| 461 | + | MaxTextureSize int `json:"max_texture_size"` | |||
| 462 | + | HardwareAccelerated bool `json:"hardware_accelerated"` | |||
| 463 | + | } `json:"data"` | |||
| 464 | + | } | |||
| 465 | + | ||||
| 466 | + | if err := json.Unmarshal([]byte(payload), &msg); err != nil { | |||
| 467 | + | log.Printf("[webkit] Failed to parse rendering backend message: %v", err) | |||
| 468 | + | return false | |||
| 469 | + | } | |||
| 470 | + | ||||
| 471 | + | if msg.Type != "rendering_backend_detection" { | |||
| 472 | + | return false | |||
| 473 | + | } | |||
| 474 | + | ||||
| 475 | + | // Log the detected rendering backend information | |||
| 476 | + | backendType := "SOFTWARE" | |||
| 477 | + | if msg.Data.HardwareAccelerated { | |||
| 478 | + | backendType = "HARDWARE" | |||
| 479 | + | } | |||
| 480 | + | ||||
| 481 | + | log.Printf("[webkit] Detected rendering backend: %s", backendType) | |||
| 482 | + | log.Printf("[webkit] WebGL available: %v", msg.Data.WebGLAvailable) | |||
| 483 | + | log.Printf("[webkit] Renderer: %s", msg.Data.Renderer) | |||
| 484 | + | log.Printf("[webkit] Vendor: %s", msg.Data.Vendor) | |||
| 485 | + | log.Printf("[webkit] Version: %s", msg.Data.Version) | |||
| 486 | + | log.Printf("[webkit] Max texture size: %d", msg.Data.MaxTextureSize) | |||
| 487 | + | ||||
| 488 | + | return true | |||
| 489 | + | } | |||