summaryrefslogtreecommitdiff
path: root/indra/newview/scripts/lua/UI.lua
blob: eb1a4017c7236f18e4a607cd8264c82c54b3b6d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
-- Engage the viewer's UI

local leap = require 'leap'
local Timer = (require 'timers').Timer
local mapargs = require 'mapargs'

local UI = {}

-- ***************************************************************************
--  registered menu actions
-- ***************************************************************************
function UI.call(func, parameter)
    -- 'call' is fire-and-forget
    leap.request('UI', {op='call', ['function']=func, parameter=parameter})
end

function UI.getValue(path)
    return leap.request('UI', {op='getValue', path=path})['value']
end

-- ***************************************************************************
--  UI views
-- ***************************************************************************
-- Either:
-- wreq{op='Something', a=1, b=2, ...}
-- or:
-- (args should be local, as this wreq() call modifies it)
-- local args = {a=1, b=2, ...}
-- wreq('Something', args)
local function wreq(op_or_data, data_if_op)
    if data_if_op ~= nil then
        -- this is the wreq(op, data) form
        data_if_op.op = op_or_data
        op_or_data = data_if_op
    end
    return leap.request('LLWindow', op_or_data)
end

-- omit 'parent' to list all view paths
function UI.listviews(parent)
    return wreq{op='getPaths', under=parent}
end

function UI.viewinfo(path)
    return wreq{op='getInfo', path=path}
end

-- ***************************************************************************
--  mouse actions
-- ***************************************************************************
-- pass a table:
-- UI.click{path=path
--          [, button='LEFT' | 'CENTER' | 'RIGHT']
--          [, x=x, y=y]
--          [, hold=duration]}
function UI.click(...)
    local args = mapargs('path,button,x,y,hold', ...)
    args.button = args.button or 'LEFT'
    local hold = args.hold or 1.0
    wreq('mouseMove', args)
    wreq('mouseDown', args)
    Timer(hold, 'wait')
    wreq('mouseUp', args)
end

-- pass a table as for UI.click()
function UI.doubleclick(...)
    local args = mapargs('path,button,x,y', ...)
    args.button = args.button or 'LEFT'
    wreq('mouseDown', args)
    wreq('mouseUp',   args)
    wreq('mouseDown', args)
    wreq('mouseUp',   args)
end

-- UI.drag{path=, xoff=, yoff=}
function UI.drag(...)
    local args = mapargs('path,xoff,yoff', ...)
    -- query the specified path
    local rect = UI.viewinfo(args.path).rect
    local centerx = math.floor(rect.left   + (rect.right - rect.left)/2)
    local centery = math.floor(rect.bottom + (rect.top   - rect.bottom)/2)
    wreq{op='mouseMove', path=args.path, x=centerx, y=centery}
    wreq{op='mouseDown', path=args.path, button='LEFT'}
    wreq{op='mouseMove', path=args.path, x=centerx + args.xoff, y=centery + args.yoff}
    wreq{op='mouseUp',   path=args.path, button='LEFT'}
end

-- ***************************************************************************
--  keyboard actions
-- ***************************************************************************
-- pass a table:
-- UI.keypress{
--     [path=path]                      -- if omitted, default input field
--     [, char='x']                     -- requires one of char, keycode, keysym
--     [, keycode=120]
--     keysym per https://github.com/secondlife/viewer/blob/main/indra/llwindow/llkeyboard.cpp#L68-L124
--     [, keysym='Enter']
--     [, mask={'SHIFT', 'CTL', 'ALT', 'MAC_CONTROL'}]  -- some subset of these
--     }
function UI.keypress(...)
    local args = mapargs('path,char,keycode,keysym,mask', ...)
    if args.char == '\n' then
        args.char = nil
        args.keysym = 'Enter'
    end
    return wreq('keyDown', args)
end

-- UI.type{text=, path=}
function UI.type(...)
    local args = mapargs('text,path', ...)
    if #args.text > 0 then
        -- The caller's path may be specified in a way that requires recursively
        -- searching parts of the LLView tree. No point in doing that more than
        -- once. Capture the actual path found by that first call and use that for
        -- subsequent calls.
        local path = UI.keypress{path=args.path, char=string.sub(args.text, 1, 1)}.path
        for i = 2, #args.text do
            UI.keypress{path=path, char=string.sub(args.text, i, i)}
        end
    end
end

return UI