Initial work to fix mouse actions

This commit is contained in:
Kenneth Shaw 2017-02-08 21:35:12 +07:00
parent 5bef7dce13
commit 4137fe57cc
2 changed files with 82 additions and 29 deletions

View File

@ -18,32 +18,60 @@ var (
// MouseAction is a mouse action.
func MouseAction(typ input.MouseType, x, y int64, opts ...MouseOption) Action {
f := input.DispatchMouseEvent(typ, x, y)
me := input.DispatchMouseEvent(typ, x, y)
// apply opts
for _, o := range opts {
f = o(f)
me = o(me)
}
return f
return me
}
// MouseClickXY sends a left mouse button click at the X, Y location.
// MouseClickXY sends a left mouse button click (ie, mousePressed and
// mouseReleased event) at the X, Y location.
func MouseClickXY(x, y int64, opts ...MouseOption) Action {
return Tasks{
MouseAction(input.MousePressed, x, y, append(opts, Button(input.ButtonLeft), ClickCount(1))...),
MouseAction(input.MouseReleased, x, y, append(opts, Button(input.ButtonLeft), ClickCount(1))...),
}
return ActionFunc(func(ctxt context.Context, h cdp.FrameHandler) error {
me := &input.DispatchMouseEventParams{
Type: input.MousePressed,
X: x,
Y: y,
Button: input.ButtonLeft,
ClickCount: 1,
}
// apply opts
for _, o := range opts {
me = o(me)
}
err := me.Do(ctxt, h)
if err != nil {
return err
}
me.Type = input.MouseReleased
return me.Do(ctxt, h)
})
}
// MouseActionNode dispatches a mouse event at the center of a specified node.
func MouseActionNode(n *cdp.Node, opts ...MouseOption) Action {
return ActionFunc(func(ctxt context.Context, h cdp.FrameHandler) error {
var err error
/*err = dom.Focus(n.NodeID).Do(ctxt, h)
if err != nil {
return err
}*/
box, err := dom.GetBoxModel(n.NodeID).Do(ctxt, h)
if err != nil {
return err
}
c := len(box.Content)
if c%2 != 0 {
if c%2 != 0 || c < 1 {
return ErrInvalidDimensions
}
@ -52,29 +80,57 @@ func MouseActionNode(n *cdp.Node, opts ...MouseOption) Action {
x += int64(box.Content[i])
y += int64(box.Content[i+1])
}
x /= int64(c / 2)
y /= int64(c / 2)
return MouseClickXY(x/int64(c/2), y/int64(c/2), opts...).Do(ctxt, h)
/*var pos []int64
err = EvaluateAsDevTools(fmt.Sprintf(scrollJS, x, y), &pos).Do(ctxt, h)*/
return MouseClickXY(x, y, opts...).Do(ctxt, h)
})
}
// MouseOption is a mouse action option.
type MouseOption func(*input.DispatchMouseEventParams) *input.DispatchMouseEventParams
// Button is a mouse action option to set the button to click.
func Button(button input.ButtonType) MouseOption {
// Button is a mouse action option to set the button to click from a string.
func Button(btn string) MouseOption {
return ButtonType(input.ButtonType(btn))
}
// ButtonType is a mouse action option to set the button to click.
func ButtonType(button input.ButtonType) MouseOption {
return func(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
return p.WithButton(button)
}
}
// ButtonString is a mouse action option to set the button to click as a
// string.
func ButtonString(btn string) MouseOption {
return Button(input.ButtonType(btn))
// ButtonLeft is a mouse action option to set the button clicked as the left
// mouse button.
func ButtonLeft(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
return p.WithButton(input.ButtonLeft)
}
// ButtonModifiers is a mouse action option to add additional modifiers for the
// button.
// ButtonMiddle is a mouse action option to set the button clicked as the middle
// mouse button.
func ButtonMiddle(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
return p.WithButton(input.ButtonMiddle)
}
// ButtonRight is a mouse action option to set the button clicked as the right
// mouse button.
func ButtonRight(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
return p.WithButton(input.ButtonRight)
}
// ButtonNone is a mouse action option to set the button clicked as none (used
// for mouse movements).
func ButtonNone(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
return p.WithButton(input.ButtonNone)
}
// ButtonModifiers is a mouse action option to add additional input modifiers
// for a button click.
func ButtonModifiers(modifiers ...input.Modifier) MouseOption {
return func(p *input.DispatchMouseEventParams) *input.DispatchMouseEventParams {
for _, m := range modifiers {
@ -92,11 +148,10 @@ func ClickCount(n int) MouseOption {
}
// KeyAction will synthesize a keyDown, char, and keyUp event for each rune
// contained in keys along with any supplied key options. Well known KeyCode
// runes will not synthesize the char event.
// contained in keys along with any supplied key options.
//
// Note: KeyCodeCR and KeyCodeLF are exceptions to the above, and a char of
// KeyCodeCR ('\r') will be synthesized for both.
// Note: only well known, "printable" characters will have "char" events
// synthesized.
func KeyAction(keys string, opts ...KeyOption) Action {
return ActionFunc(func(ctxt context.Context, h cdp.FrameHandler) error {
var err error

View File

@ -13,7 +13,6 @@ import (
"github.com/disintegration/imaging"
"github.com/knq/chromedp/cdp"
"github.com/knq/chromedp/cdp/dom"
"github.com/knq/chromedp/cdp/input"
"github.com/knq/chromedp/cdp/page"
)
@ -161,6 +160,7 @@ func Text(sel interface{}, text *string, opts ...QueryOption) Action {
if text == nil {
panic("text cannot be nil")
}
return QueryAfter(sel, func(ctxt context.Context, h cdp.FrameHandler, nodes ...*cdp.Node) error {
if len(nodes) < 1 {
return fmt.Errorf("selector `%s` did not return any nodes", sel)
@ -270,7 +270,7 @@ func Click(sel interface{}, opts ...QueryOption) Action {
return fmt.Errorf("selector `%s` did not return any nodes", sel)
}
return MouseActionNode(nodes[0], Button(input.ButtonLeft), ClickCount(1)).Do(ctxt, h)
return MouseActionNode(nodes[0], ClickCount(1)).Do(ctxt, h)
}, append(opts, ElementVisible)...)
}
@ -281,7 +281,7 @@ func DoubleClick(sel interface{}, opts ...QueryOption) Action {
return fmt.Errorf("selector `%s` did not return any nodes", sel)
}
return MouseActionNode(nodes[0], Button(input.ButtonLeft), ClickCount(2)).Do(ctxt, h)
return MouseActionNode(nodes[0], ButtonLeft, ClickCount(2)).Do(ctxt, h)
}, append(opts, ElementVisible)...)
}
@ -293,7 +293,7 @@ func Hover(sel interface{}, opts ...QueryOption) Action {
return fmt.Errorf("selector `%s` did not return any nodes", sel)
}
return MouseActionNode(nodes[0], Button(input.ButtonNone)).Do(ctxt, h)
return MouseActionNode(nodes[0], ButtonNone).Do(ctxt, h)
}, append(opts, ElementVisible)...)
}
@ -331,7 +331,7 @@ func Screenshot(sel interface{}, picbuf *[]byte, opts ...QueryOption) Action {
return ErrInvalidBoxModel
}
// scroll to node location
// scroll to node position
var pos []int
err = EvaluateAsDevTools(fmt.Sprintf(scrollJS, int64(box.Margin[0]), int64(box.Margin[1])), &pos).Do(ctxt, h)
if err != nil {
@ -435,8 +435,6 @@ const (
/*
ScrollTo
Title
SetTitle
OuterHTML