-
Notifications
You must be signed in to change notification settings - Fork 93
/
lock_state.go
207 lines (179 loc) · 5.47 KB
/
lock_state.go
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// SPDX-FileCopyrightText: 2018 - 2022 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later
package keybinding
import (
"errors"
"fmt"
"os"
"time"
"github.com/godbus/dbus/v5"
"github.com/linuxdeepin/dde-daemon/keybinding/shortcuts"
kwayland "github.com/linuxdeepin/go-dbus-factory/session/org.deepin.dde.kwayland1"
x "github.com/linuxdeepin/go-x11-client"
"github.com/linuxdeepin/go-x11-client/ext/test"
"github.com/linuxdeepin/go-x11-client/util/keysyms"
)
// NumLockState 数字锁定键状态
type NumLockState uint
const (
NumLockOff NumLockState = iota // 关闭,不能输入数字,是方向键
NumLockOn // 开启,能输入数字
NumLockUnknown // 未知,出错
)
func (s NumLockState) String() string {
switch s {
case NumLockOff:
return "off"
case NumLockOn:
return "on"
case NumLockUnknown:
return "unknown"
default:
return fmt.Sprintf("invalid-num-lock-state(%d)", s)
}
}
// CapsLockState 大小写锁定键状态
type CapsLockState uint
const (
CapsLockOff CapsLockState = iota // 关闭,默认输入小写字母
CapsLockOn // 开启,默认输入大写字母
CapsLockUnknown // 未知,出错
)
// 查询 NumLock 数字锁定键状态
func queryNumLockState(conn *x.Conn) (NumLockState, error) {
rootWin := conn.GetDefaultScreen().Root
queryPointerReply, err := x.QueryPointer(conn, rootWin).Reply(conn)
if err != nil {
return NumLockUnknown, err
}
logger.Debugf("query pointer reply %#v", queryPointerReply)
on := queryPointerReply.Mask&x.ModMask2 != 0
if on {
return NumLockOn, nil
} else {
return NumLockOff, nil
}
}
// 查询 CapsLock 大小写锁定键状态
func queryCapsLockState(conn *x.Conn) (CapsLockState, error) {
rootWin := conn.GetDefaultScreen().Root
queryPointerReply, err := x.QueryPointer(conn, rootWin).Reply(conn)
if err != nil {
return CapsLockUnknown, err
}
logger.Debugf("query pointer reply %#v", queryPointerReply)
on := queryPointerReply.Mask&x.ModMaskLock != 0
if on {
return CapsLockOn, nil
} else {
return CapsLockOff, nil
}
}
func setNumLockWl(wl kwayland.OutputManagement, conn *x.Conn, state NumLockState) error {
if !(state == NumLockOff || state == NumLockOn) {
return errors.New("invalid num lock state")
}
logger.Debug("setNumLockWl", state)
var state0 NumLockState
if len(os.Getenv("WAYLAND_DISPLAY")) != 0 {
sessionBus, err := dbus.SessionBus()
if err != nil {
return err
}
time.Sleep(200 * time.Millisecond) //+ 添加200ms延时,保证在dde-system-daemon中先获取状态;
sessionObj := sessionBus.Object("org.kde.KWin", "/Xkb")
var ret int32
err = sessionObj.Call("org.kde.kwin.Xkb.getLeds", 0).Store(&ret)
if err != nil {
logger.Warning(err)
return err
}
if 0 == (ret & 0x1) {
state0 = NumLockOff
} else {
state0 = NumLockOn
}
} else {
var err error
state0, err = queryNumLockState(conn)
if err != nil {
return err
}
}
if state0 != state {
return wl.WlSimulateKey(0, 69) //69-kwin对应的NumLock
}
return nil
}
// 设置 NumLock 数字锁定键状态
func setNumLockX11(conn *x.Conn, keySymbols *keysyms.KeySymbols, state NumLockState) error {
logger.Debug("setNumLockState", state)
if !(state == NumLockOff || state == NumLockOn) {
return errors.New("invalid num lock state")
}
state0, err := queryNumLockState(conn)
if err != nil {
return err
}
if state0 != state {
return changeNumLockState(conn, keySymbols)
}
return nil
}
// 设置 NumLock 数字锁定键状态
func setNumLockState(wl kwayland.OutputManagement, conn *x.Conn, keySymbols *keysyms.KeySymbols, state NumLockState) error {
if _useWayland {
return setNumLockWl(wl, conn, state)
}
return setNumLockX11(conn, keySymbols, state)
}
// 设置 CapsLock 大小写锁定键状态
func setCapsLockState(conn *x.Conn, keySymbols *keysyms.KeySymbols, state CapsLockState) error {
if !(state == CapsLockOff || state == CapsLockOn) {
return errors.New("invalid caps lock state")
}
state0, err := queryCapsLockState(conn)
if err != nil {
return err
}
if state0 != state {
return changeCapsLockState(conn, keySymbols)
}
return nil
}
// 修改 NumLock 数字锁定键状态,模拟一次相应的键按下和释放。
func changeNumLockState(conn *x.Conn, keySymbols *keysyms.KeySymbols) (err error) {
// get Num_Lock keycode
numLockKeycode, err := shortcuts.GetKeyFirstCode(keySymbols, "Num_Lock")
if err != nil {
return err
}
logger.Debug("numLockKeycode is", numLockKeycode)
return simulatePressReleaseKey(conn, numLockKeycode)
}
// 修改 CapsLock 大小写锁定键状态,模拟一次相应的键按下释放。
func changeCapsLockState(conn *x.Conn, keySymbols *keysyms.KeySymbols) (err error) {
// get Caps_Lock keycode
capsLockKeycode, err := shortcuts.GetKeyFirstCode(keySymbols, "Caps_Lock")
if err != nil {
return err
}
logger.Debug("capsLockKeycode is", capsLockKeycode)
return simulatePressReleaseKey(conn, capsLockKeycode)
}
// 模拟键的按下和释放
func simulatePressReleaseKey(conn *x.Conn, code x.Keycode) error {
rootWin := conn.GetDefaultScreen().Root
// fake key press
err := test.FakeInputChecked(conn, x.KeyPressEventCode, byte(code), x.TimeCurrentTime, rootWin, 0, 0, 0).Check(conn)
if err != nil {
return err
}
// fake key release
err = test.FakeInputChecked(conn, x.KeyReleaseEventCode, byte(code), x.TimeCurrentTime, rootWin, 0, 0, 0).Check(conn)
if err != nil {
return err
}
return nil
}