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

View File

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