Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/platform/linuxbsd/freedesktop_at_spi_monitor.cpp
10277 views
1
/**************************************************************************/
2
/* freedesktop_at_spi_monitor.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "freedesktop_at_spi_monitor.h"
32
33
#ifdef DBUS_ENABLED
34
35
#include "core/os/os.h"
36
37
#ifdef SOWRAP_ENABLED
38
#include "dbus-so_wrap.h"
39
#else
40
#include <dbus/dbus.h>
41
#endif
42
43
#include <unistd.h>
44
45
#define BUS_OBJECT_NAME "org.a11y.Bus"
46
#define BUS_OBJECT_PATH "/org/a11y/bus"
47
48
#define BUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties"
49
50
void FreeDesktopAtSPIMonitor::monitor_thread_func(void *p_userdata) {
51
FreeDesktopAtSPIMonitor *mon = (FreeDesktopAtSPIMonitor *)p_userdata;
52
53
DBusError error;
54
dbus_error_init(&error);
55
56
DBusConnection *bus = dbus_bus_get(DBUS_BUS_SESSION, &error);
57
if (dbus_error_is_set(&error)) {
58
dbus_error_free(&error);
59
mon->supported.clear();
60
return;
61
}
62
63
static const char *iface = "org.a11y.Status";
64
static const char *member_ac = "IsEnabled";
65
static const char *member_sr = "ScreenReaderEnabled";
66
67
while (!mon->exit_thread.is_set()) {
68
DBusMessage *message = dbus_message_new_method_call(BUS_OBJECT_NAME, BUS_OBJECT_PATH, BUS_INTERFACE_PROPERTIES, "Get");
69
70
dbus_message_append_args(
71
message,
72
DBUS_TYPE_STRING, &iface,
73
DBUS_TYPE_STRING, &member_ac,
74
DBUS_TYPE_INVALID);
75
76
DBusMessage *reply = dbus_connection_send_with_reply_and_block(bus, message, 50, &error);
77
dbus_message_unref(message);
78
79
if (!dbus_error_is_set(&error)) {
80
DBusMessageIter iter, iter_variant, iter_struct;
81
dbus_bool_t result;
82
dbus_message_iter_init(reply, &iter);
83
dbus_message_iter_recurse(&iter, &iter_variant);
84
switch (dbus_message_iter_get_arg_type(&iter_variant)) {
85
case DBUS_TYPE_STRUCT: {
86
dbus_message_iter_recurse(&iter_variant, &iter_struct);
87
if (dbus_message_iter_get_arg_type(&iter_struct) == DBUS_TYPE_BOOLEAN) {
88
dbus_message_iter_get_basic(&iter_struct, &result);
89
if (result) {
90
mon->ac_enabled.set();
91
} else {
92
mon->ac_enabled.clear();
93
}
94
}
95
} break;
96
case DBUS_TYPE_BOOLEAN: {
97
dbus_message_iter_get_basic(&iter_variant, &result);
98
if (result) {
99
mon->ac_enabled.set();
100
} else {
101
mon->ac_enabled.clear();
102
}
103
} break;
104
default:
105
break;
106
}
107
dbus_message_unref(reply);
108
} else {
109
dbus_error_free(&error);
110
}
111
112
message = dbus_message_new_method_call(BUS_OBJECT_NAME, BUS_OBJECT_PATH, BUS_INTERFACE_PROPERTIES, "Get");
113
114
dbus_message_append_args(
115
message,
116
DBUS_TYPE_STRING, &iface,
117
DBUS_TYPE_STRING, &member_sr,
118
DBUS_TYPE_INVALID);
119
120
reply = dbus_connection_send_with_reply_and_block(bus, message, 50, &error);
121
dbus_message_unref(message);
122
123
if (!dbus_error_is_set(&error)) {
124
DBusMessageIter iter, iter_variant, iter_struct;
125
dbus_bool_t result;
126
dbus_message_iter_init(reply, &iter);
127
dbus_message_iter_recurse(&iter, &iter_variant);
128
switch (dbus_message_iter_get_arg_type(&iter_variant)) {
129
case DBUS_TYPE_STRUCT: {
130
dbus_message_iter_recurse(&iter_variant, &iter_struct);
131
if (dbus_message_iter_get_arg_type(&iter_struct) == DBUS_TYPE_BOOLEAN) {
132
dbus_message_iter_get_basic(&iter_struct, &result);
133
if (result) {
134
mon->sr_enabled.set();
135
} else {
136
mon->sr_enabled.clear();
137
}
138
}
139
} break;
140
case DBUS_TYPE_BOOLEAN: {
141
dbus_message_iter_get_basic(&iter_variant, &result);
142
if (result) {
143
mon->sr_enabled.set();
144
} else {
145
mon->sr_enabled.clear();
146
}
147
} break;
148
default:
149
break;
150
}
151
dbus_message_unref(reply);
152
} else {
153
dbus_error_free(&error);
154
}
155
156
usleep(50000);
157
}
158
159
dbus_connection_unref(bus);
160
}
161
162
FreeDesktopAtSPIMonitor::FreeDesktopAtSPIMonitor() {
163
supported.set();
164
sr_enabled.clear();
165
exit_thread.clear();
166
167
thread.start(FreeDesktopAtSPIMonitor::monitor_thread_func, this);
168
}
169
170
FreeDesktopAtSPIMonitor::~FreeDesktopAtSPIMonitor() {
171
exit_thread.set();
172
if (thread.is_started()) {
173
thread.wait_to_finish();
174
}
175
}
176
177
#endif // DBUS_ENABLED
178
179