Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions example/simpleDemo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func main() {
gutter.OptionPixelRatio(1.2),
gutter.OptionVMArguments([]string{"--dart-non-checked-mode", "--observatory-port=50300"}),
gutter.OptionAddPluginReceiver(ownPlugin, "plugin_demo"),
gutter.OptionKeyboardLayout(gutter.KeyboardAzertyLayout),
}

if err = gutter.Run(options...); err != nil {
Expand Down
112 changes: 60 additions & 52 deletions gutter.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,73 +93,74 @@ func glfwMouseButtonCallback(window *glfw.Window, key glfw.MouseButton, action g

var state = textModel{}

func glfwKeyCallback(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
func glfwKey(keyboardLayout KeyboardShortcuts) func(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {

if key == glfw.KeyEscape && action == glfw.Press {
w.SetShouldClose(true)
}
return func(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
if key == glfw.KeyEscape && action == glfw.Press {
w.SetShouldClose(true)
}

if action == glfw.Repeat || action == glfw.Press {
if state.clientID != 0 {
if action == glfw.Repeat || action == glfw.Press {
if state.clientID != 0 {

switch key {
case glfw.KeyEnter:
if mods == glfw.ModControl {
performAction(w, "done")
} else {
state.addChar([]rune{'\n'})
performAction(w, "newline")
}
switch key {
case glfw.KeyEnter:
if mods == glfw.ModControl {
performAction(w, "done")
} else {
state.addChar([]rune{'\n'})
performAction(w, "newline")
}

case glfw.KeyHome:
state.MoveCursorHome(int(mods))
case glfw.KeyHome:
state.MoveCursorHome(int(mods))

case glfw.KeyEnd:
state.MoveCursorEnd(int(mods))
case glfw.KeyEnd:
state.MoveCursorEnd(int(mods))

case glfw.KeyLeft:
state.MoveCursorLeft(int(mods))
case glfw.KeyLeft:
state.MoveCursorLeft(int(mods))

case glfw.KeyRight:
state.MoveCursorRight(int(mods))
case glfw.KeyRight:
state.MoveCursorRight(int(mods))

case glfw.KeyDelete:
state.Delete(int(mods))
case glfw.KeyDelete:
state.Delete(int(mods))

case glfw.KeyBackspace:
state.Backspace(int(mods))
case glfw.KeyBackspace:
state.Backspace(int(mods))

case glfw.KeyA:
if mods == glfw.ModControl {
state.SelectAll()
}
case keyboardLayout.SelectAll:
if mods == glfw.ModControl {
state.SelectAll()
}

case glfw.KeyC:
if mods == glfw.ModControl && state.isSelected() {
_, _, selectedContent := state.GetSelectedText()
w.SetClipboardString(selectedContent)
}
case keyboardLayout.Copy:
if mods == glfw.ModControl && state.isSelected() {
_, _, selectedContent := state.GetSelectedText()
w.SetClipboardString(selectedContent)
}

case glfw.KeyX:
if mods == glfw.ModControl && state.isSelected() {
_, _, selectedContent := state.GetSelectedText()
w.SetClipboardString(selectedContent)
state.RemoveSelectedText()
}
case keyboardLayout.Cut:
if mods == glfw.ModControl && state.isSelected() {
_, _, selectedContent := state.GetSelectedText()
w.SetClipboardString(selectedContent)
state.RemoveSelectedText()
}

case glfw.KeyV:
if mods == glfw.ModControl {
var clpString, err = w.GetClipboardString()
if err != nil {
log.Printf("unable to get the clipboard content: %v\n", err)
} else {
state.addChar([]rune(clpString))
case keyboardLayout.Paste:
if mods == glfw.ModControl {
var clpString, err = w.GetClipboardString()
if err != nil {
log.Printf("unable to get the clipboard content: %v\n", err)
} else {
state.addChar([]rune(clpString))
}
}
}
}
}
}

}

func glfwWindowSizeCallback(window *glfw.Window, width int, height int) {
Expand Down Expand Up @@ -242,6 +243,13 @@ func runFlutter(window *glfw.Window, c config) *flutter.EngineOpenGL {

width, height := window.GetFramebufferSize()
glfwWindowSizeCallback(window, width, height)
var glfwKeyCallback func(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey)

if c.KeyboardLayout != nil {
glfwKeyCallback = glfwKey(*c.KeyboardLayout)
} else {
glfwKeyCallback = glfwKey(KeyboardQwertyLayout)
}

window.SetKeyCallback(glfwKeyCallback)
window.SetFramebufferSizeCallback(glfwWindowSizeCallback)
Expand Down Expand Up @@ -286,11 +294,11 @@ func performAction(window *glfw.Window, action string) {
"TextInputAction." + action,
})
message := flutter.Message{
Args: actionArgs,
Method:"TextInputClient.performAction",
Args: actionArgs,
Method: "TextInputClient.performAction",
}
var mess = &flutter.PlatformMessage{
Channel:textInputChannel,
Channel: textInputChannel,
Message: message,
}
flutterOGL := flutter.SelectEngine(0)
Expand Down
19 changes: 19 additions & 0 deletions keyboard.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package gutter

import "github.com/go-gl/glfw/v3.2/glfw"

// KeyboardQwertyLayout is the default key for shortcuts (US-layout)
var KeyboardQwertyLayout = KeyboardShortcuts{
Cut: glfw.KeyX,
Copy: glfw.KeyC,
Paste: glfw.KeyV,
SelectAll: glfw.KeyA,
}

// KeyboardAzertyLayout gives an Azerty layout (french)
var KeyboardAzertyLayout = KeyboardShortcuts{
Cut: glfw.KeyX,
Copy: glfw.KeyC,
Paste: glfw.KeyV,
SelectAll: glfw.KeyQ,
}
18 changes: 18 additions & 0 deletions option.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@ func OptionAddPluginReceiver(handler PluginReceivers, channelName string) Option
}
}

// OptionKeyboardLayout allow application to support keyboard that have a different layout
// when the FlutterEngine send a PlatformMessage to the Embedder
func OptionKeyboardLayout(keyboardLayout KeyboardShortcuts) Option {
return func(c *config) {
c.KeyboardLayout = &keyboardLayout
}
}

type config struct {
WindowDimension struct {
x int
Expand All @@ -97,6 +105,16 @@ type config struct {
PixelRatio float64
VMArguments []string
PlatformMessageReceivers map[string][]PluginReceivers // The Key is the Channel name.
KeyboardLayout *KeyboardShortcuts
}

// KeyboardShortcuts Struct where user can define his own keyboard shortcut.
// This will allow application to support keyboard layout different from US layout
type KeyboardShortcuts struct {
Cut glfw.Key
Copy glfw.Key
Paste glfw.Key
SelectAll glfw.Key
}

func (t config) merge(options ...Option) config {
Expand Down