From 078a23e0e080b9eca82c8ef9a582675d81e2f30f Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Sat, 8 Feb 2025 08:36:08 -0600 Subject: [PATCH] detect double click --- eventMouse.go | 26 +++++++++++--------------- eventMouseClick.go | 29 ++++++++--------------------- eventMouseMove.go | 27 ++++++++++++++++----------- init.go | 1 + structs.go | 8 +++----- 5 files changed, 39 insertions(+), 52 deletions(-) diff --git a/eventMouse.go b/eventMouse.go index 6b99c65..05568d9 100644 --- a/eventMouse.go +++ b/eventMouse.go @@ -13,8 +13,6 @@ import ( ) func mouseUp(g *gocui.Gui, v *gocui.View) error { - w, h := g.MousePosition() - // useful to debug everything that is being clicked on /* for _, tk := range findByXY(w, h) { @@ -22,16 +20,13 @@ func mouseUp(g *gocui.Gui, v *gocui.View) error { } */ - if time.Since(me.mouse.down) < me.mouse.clicktime { - log.Info("was a mouse click, not a drag") - } - me.mouse.mouseUp = true - me.globalMouseDown = false - me.currentDrag = nil - - dropdownUnclicked(w, h) + me.mouse.globalMouseDown = false + me.mouse.currentDrag = nil + if time.Since(me.mouse.down) < me.mouse.clicktime { + doMouseClick(me.mouse.downW, me.mouse.downH) + } return nil } @@ -40,7 +35,10 @@ func mouseUp(g *gocui.Gui, v *gocui.View) error { // the right response for the toolkit user's app func mouseDown(g *gocui.Gui, v *gocui.View) error { if me.mouse.mouseUp { - me.globalMouseDown = true + if time.Since(me.mouse.down) < me.mouse.doubletime { + log.Info("double click") + } + me.mouse.globalMouseDown = true me.mouse.mouseUp = false me.mouse.down = time.Now() w, h := g.MousePosition() @@ -55,8 +53,6 @@ func mouseDown(g *gocui.Gui, v *gocui.View) error { } w, h := g.MousePosition() - me.downW = w - me.downH = h // if the dropdown is active, never do anything else if me.dropdown.active { @@ -123,13 +119,13 @@ func mouseDown(g *gocui.Gui, v *gocui.View) error { } if tk.node.WidgetType == widget.Stdout { // tk.dumpWidget("stdout fixme drag()" + tk.labelN) - me.currentDrag = tk + me.mouse.currentDrag = tk tk.dragW = w - tk.gocuiSize.w0 tk.dragH = h - tk.gocuiSize.h0 return nil } // tk.dumpWidget("mouse drag()" + tk.labelN) - me.currentDrag = tk + me.mouse.currentDrag = tk tk.dragW = w - tk.gocuiSize.w0 tk.dragH = h - tk.gocuiSize.h0 return nil diff --git a/eventMouseClick.go b/eventMouseClick.go index 675aeac..2b725a6 100644 --- a/eventMouseClick.go +++ b/eventMouseClick.go @@ -6,7 +6,6 @@ package main import ( "fmt" - "github.com/awesome-gocui/gocui" "go.wit.com/log" "go.wit.com/widget" ) @@ -109,18 +108,15 @@ func (tk *guiWidget) doWidgetClick(w int, h int) { } } -// sends the mouse click to a widget underneath -func clickOLD(g *gocui.Gui, v *gocui.View) error { - mouseW, mouseH := me.baseGui.MousePosition() - - w := mouseW - h := mouseH +// handles a mouse click +func doMouseClick(w int, h int) { + dropdownUnclicked(w, h) // Flag widgets (dropdown menus, etc) are the highest priority. ALWAYS SEND MOUSE CLICKS THERE FIRST for _, tk := range findByXY(w, h) { if tk.node.WidgetType == widget.Flag { tk.doWidgetClick(w, h) - return nil + return } } @@ -128,7 +124,7 @@ func clickOLD(g *gocui.Gui, v *gocui.View) error { for _, tk := range findByXY(w, h) { if tk.node.WidgetType == widget.Button { tk.doWidgetClick(w, h) - return nil + return } } @@ -140,18 +136,9 @@ func clickOLD(g *gocui.Gui, v *gocui.View) error { continue } tk.doWidgetClick(w, h) - return nil + return } - log.Log(GOCUI, "click() nothing was at:", v.Name(), mouseW, mouseH) - return nil - /* - // not sure what SetCurrentView() does right now. it was here before - // SetCurrentView dies if it's sent an non-existent view - if _, err := g.SetCurrentView(v.Name()); err != nil { - log.Log(GOCUI, "click() END v.Name =", v.Name(), "err =", err) - // return err // return causes gocui.MainLoop() to exit. Do we ever want that to happen here? - return nil - } - */ + log.Log(GOCUI, "click() nothing was at:", w, h) + return } diff --git a/eventMouseMove.go b/eventMouseMove.go index b6c43ae..e928265 100644 --- a/eventMouseMove.go +++ b/eventMouseMove.go @@ -38,6 +38,11 @@ func mouseMove(g *gocui.Gui) { return } + if me.dropdown.active || me.textbox.active { + // can't drag or do anything when dropdown or textbox are visible + return + } + w, h := g.MousePosition() // toggle off all highlight vies except for whatever is under the mouse for _, view := range g.Views() { @@ -56,30 +61,30 @@ func mouseMove(g *gocui.Gui) { return } - if me.globalMouseDown && (me.dropdown.active || me.textbox.active) { + if me.mouse.globalMouseDown && (me.dropdown.active || me.textbox.active) { log.Info("can't drag while dropdown or textbox are active", w, h) return } - if me.globalMouseDown { + if me.mouse.globalMouseDown { // log.Info("msgMouseDown == true") // plugin will segfault if you don't keep this inside a check for msgMouseDown // don't move this code out of here var found bool = false - if me.currentDrag != nil { - // me.currentDrag.dumpWidget(fmt.Sprintf("MM (%3d,%3d)", w, h)) - me.currentDrag.moveNew() + if me.mouse.currentDrag != nil { + // me.mouse.currentDrag.dumpWidget(fmt.Sprintf("MM (%3d,%3d)", w, h)) + me.mouse.currentDrag.moveNew() return } // new function that is smarter if tk := findWindowUnderMouse(); tk != nil { - me.currentDrag = tk + me.mouse.currentDrag = tk return } // first look for windows for _, tk := range findByXY(w, h) { if tk.node.WidgetType == widget.Window { - me.currentDrag = tk + me.mouse.currentDrag = tk return } } @@ -87,20 +92,20 @@ func mouseMove(g *gocui.Gui) { // now look for the STDOUT window for _, tk := range findByXY(w, h) { if tk.node.WidgetType == widget.Flag { - me.currentDrag = tk + me.mouse.currentDrag = tk // tk.moveNew() return } } for _, tk := range findByXY(w, h) { if tk.node.WidgetType == widget.Stdout { - me.currentDrag = tk + me.mouse.currentDrag = tk // tk.moveNew() return } /* if tk.node.WidgetType == widget.Label { - me.currentDrag = tk + me.mouse.currentDrag = tk // tk.moveNew() return } @@ -130,7 +135,7 @@ func (tk *guiWidget) moveNew() { return } if tk.node.WidgetType == widget.Stdout { - if me.stdout.resize { + if me.mouse.resize { newW := w - me.stdout.lastW newH := h - me.stdout.lastH me.stdout.w = newW diff --git a/init.go b/init.go index a243fd2..3964ce0 100644 --- a/init.go +++ b/init.go @@ -52,6 +52,7 @@ func init() { me.mouse.mouseUp = true me.mouse.clicktime = time.Millisecond * 100 + me.mouse.doubletime = time.Millisecond * 300 me.myTree = tree.New() me.myTree.PluginName = "gocui" diff --git a/structs.go b/structs.go index c7368de..832e6bf 100644 --- a/structs.go +++ b/structs.go @@ -63,16 +63,12 @@ type config struct { ecount int // counts how many mouse and keyboard events have occurred supermouse bool // prints out every widget found while you move the mouse around depth int // used for listWidgets() debugging - globalMouseDown bool // yep, mouse is pressed newWindowTrigger chan *guiWidget // work around hack to redraw windows a bit after NewWindow() stdout stdout // information for the STDOUT window showDebug bool // todo: move this into config struct dropdown dropdown // the dropdown menu textbox dropdown // the textbox popup window allwin []*guiWidget // for tracking which window is next - downW int // where the mouse was pressed down - downH int // where the mouse was pressed down - currentDrag *guiWidget // what widget is currently being moved around dark bool // use a 'dark' color palette mouse mouse // mouse settings } @@ -83,6 +79,9 @@ type mouse struct { up time.Time // when the mouse was released. used to detect click vs drag clicktime time.Duration // how long is too long for a mouse click vs drag mouseUp bool // is the mouse up? + double bool // user is double clicking + doubletime time.Duration // how long is too long for double click + resize bool // mouse is resizing something downW int // where the mouse was pressed down downH int // where the mouse was pressed down currentDrag *guiWidget // what widget is currently being moved around @@ -102,7 +101,6 @@ type stdout struct { // mouseOffsetW int // the current 'w' offset // mouseOffsetH int // the current 'h' offset init bool // moves the window offscreen on startup - resize bool // user is resizing the window outputS []string // the buffer of all the output pager int // allows the user to page through the buffer }