1
/*******************************************************************************
2
**3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
3
** 10 20 30 40 50 60 70 80
7
** bubble-window-accessible.c - implements an accessible bubble window
9
** Copyright 2009 Canonical Ltd.
12
** Eitan Isaacson <eitan@ascender.com>
14
** This program is free software: you can redistribute it and/or modify it
15
** under the terms of the GNU General Public License version 3, as published
16
** by the Free Software Foundation.
18
** This program is distributed in the hope that it will be useful, but
19
** WITHOUT ANY WARRANTY; without even the implied warranties of
20
** MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
21
** PURPOSE. See the GNU General Public License for more details.
23
** You should have received a copy of the GNU General Public License along
24
** with this program. If not, see <http://www.gnu.org/licenses/>.
26
*******************************************************************************/
28
#include "bubble-window-accessible.h"
32
static void bubble_window_accessible_init (BubbleWindowAccessible* object);
33
static void bubble_window_accessible_finalize (GObject* object);
34
static void bubble_window_accessible_class_init (BubbleWindowAccessibleClass* klass);
35
static const char* bubble_window_accessible_get_name (AtkObject* obj);
36
static const char* bubble_window_accessible_get_description (AtkObject* obj);
37
static void bubble_window_real_initialize (AtkObject* obj,
39
static void atk_value_interface_init (AtkValueIface* iface);
40
static void atk_text_interface_init (AtkTextIface* iface);
41
static void bubble_window_get_current_value (AtkValue* obj,
43
static void bubble_window_get_maximum_value (AtkValue* obj,
45
static void bubble_window_get_minimum_value (AtkValue* obj,
47
static void bubble_value_changed_event (Bubble* bubble,
50
static void bubble_message_body_deleted_event (Bubble* bubble,
53
static void bubble_message_body_inserted_event (Bubble* bubble,
57
static gchar* bubble_window_get_text (AtkText *obj,
60
static gint bubble_window_get_character_count (AtkText *obj);
61
static gunichar bubble_window_get_character_at_offset (AtkText *obj,
64
static void* bubble_window_accessible_parent_class;
66
G_DEFINE_TYPE_WITH_CODE (BubbleWindowAccessible, bubble_window_accessible, GTK_TYPE_ACCESSIBLE,
67
G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init)
68
G_IMPLEMENT_INTERFACE (ATK_TYPE_VALUE, atk_value_interface_init))
71
atk_value_interface_init (AtkValueIface* iface)
73
g_return_if_fail (iface != NULL);
75
iface->get_current_value = bubble_window_get_current_value;
76
iface->get_maximum_value = bubble_window_get_maximum_value;
77
iface->get_minimum_value = bubble_window_get_minimum_value;
81
atk_text_interface_init (AtkTextIface* iface)
83
g_return_if_fail (iface != NULL);
85
iface->get_text = bubble_window_get_text;
86
iface->get_character_count = bubble_window_get_character_count;
87
iface->get_character_at_offset = bubble_window_get_character_at_offset;
92
bubble_window_accessible_init (BubbleWindowAccessible *object)
94
/* TODO: Add initialization code here */
98
bubble_window_accessible_finalize (GObject *object)
100
/* TODO: Add deinitalization code here */
102
G_OBJECT_CLASS (bubble_window_accessible_parent_class)->finalize (object);
106
bubble_window_accessible_class_init (BubbleWindowAccessibleClass *klass)
108
GObjectClass* object_class = G_OBJECT_CLASS (klass);
109
AtkObjectClass* class = ATK_OBJECT_CLASS (klass);
111
bubble_window_accessible_parent_class = g_type_class_peek_parent (klass);
113
class->get_name = bubble_window_accessible_get_name;
114
class->get_description = bubble_window_accessible_get_description;
115
class->initialize = bubble_window_real_initialize;
117
object_class->finalize = bubble_window_accessible_finalize;
121
bubble_window_real_initialize (AtkObject* obj,
124
GtkWidget* widget = GTK_WIDGET (data);
127
ATK_OBJECT_CLASS (bubble_window_accessible_parent_class)->initialize (obj, data);
129
bubble = g_object_get_data (G_OBJECT(widget), "bubble");
131
g_signal_connect (bubble,
133
G_CALLBACK (bubble_value_changed_event),
136
g_signal_connect (bubble,
137
"message-body-deleted",
138
G_CALLBACK (bubble_message_body_deleted_event),
141
g_signal_connect (bubble,
142
"message-body-inserted",
143
G_CALLBACK (bubble_message_body_inserted_event),
146
atk_object_set_role (obj, ATK_ROLE_NOTIFICATION);
150
bubble_window_accessible_new (GtkWidget *widget)
155
object = g_object_new (BUBBLE_WINDOW_TYPE_ACCESSIBLE, NULL);
157
aobj = ATK_OBJECT (object);
159
gtk_accessible_set_widget (GTK_ACCESSIBLE (aobj), widget);
161
atk_object_initialize (aobj, widget);
167
bubble_window_accessible_get_name (AtkObject* obj)
173
g_return_val_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj), "");
175
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
180
bubble = g_object_get_data (G_OBJECT (widget), "bubble");
182
g_return_val_if_fail (IS_BUBBLE (bubble), "");
185
title = bubble_get_title(bubble);
186
if (g_strcmp0(title, " ") == 0)
188
/* HACK: Titles should never be empty. This solution is extremely wrong.
189
https://bugs.launchpad.net/notify-osd/+bug/334292 */
190
const gchar* synch_str;
191
synch_str = bubble_get_synchronous(bubble);
192
if (synch_str != NULL)
203
bubble_window_accessible_get_description (AtkObject* obj)
208
g_return_val_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj), "");
210
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
215
bubble = g_object_get_data (G_OBJECT (widget), "bubble");
217
g_return_val_if_fail (IS_BUBBLE (bubble), "");
219
return bubble_get_message_body(bubble);
223
bubble_window_get_current_value (AtkValue* obj,
226
gdouble current_value;
230
g_return_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj));
232
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
237
bubble = g_object_get_data (G_OBJECT (widget), "bubble");
239
current_value = (gdouble) bubble_get_value(bubble);
241
memset (value, 0, sizeof (GValue));
242
g_value_init (value, G_TYPE_DOUBLE);
243
g_value_set_double (value,current_value);
247
bubble_window_get_maximum_value (AtkValue* obj,
250
memset (value, 0, sizeof (GValue));
251
g_value_init (value, G_TYPE_DOUBLE);
252
g_value_set_double (value, 100.0);
256
bubble_window_get_minimum_value (AtkValue* obj,
259
memset (value, 0, sizeof (GValue));
260
g_value_init (value, G_TYPE_DOUBLE);
261
g_value_set_double (value, 0.0);
265
bubble_value_changed_event (Bubble* bubble,
269
g_object_notify (G_OBJECT (obj), "accessible-value");
273
bubble_message_body_deleted_event (Bubble* bubble,
277
/* Not getting very fancy here, delete is always complete */
278
g_signal_emit_by_name (
279
obj, "text_changed::delete", 0, g_utf8_strlen (text, -1));
283
bubble_message_body_inserted_event (Bubble* bubble,
287
const gchar* message_body;
289
message_body = bubble_get_message_body (bubble);
291
g_signal_emit_by_name (
292
obj, "text_changed::insert",
293
g_utf8_strlen (message_body, -1) - g_utf8_strlen (text, -1),
294
g_utf8_strlen (message_body, -1));
298
bubble_window_get_text (AtkText *obj,
304
const gchar* body_text;
308
g_return_val_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj), g_strdup(""));
310
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
312
g_return_val_if_fail (GTK_IS_WINDOW (widget), g_strdup(""));
314
bubble = g_object_get_data (G_OBJECT(widget), "bubble");
316
if (end_offset <= start_offset)
319
body_text = bubble_get_message_body (bubble);
321
body_strlen = g_utf8_strlen(body_text, -1);
323
if (start_offset > body_strlen)
324
start_offset = body_strlen;
326
if (end_offset > body_strlen || end_offset == -1)
327
end_offset = body_strlen;
330
char_length = g_utf8_offset_to_pointer (body_text, end_offset) -
331
g_utf8_offset_to_pointer (body_text, start_offset);
333
return g_strndup (g_utf8_offset_to_pointer(body_text, start_offset),
338
bubble_window_get_character_count (AtkText *obj)
343
g_return_val_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj), 0);
345
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
350
bubble = g_object_get_data (G_OBJECT (widget), "bubble");
352
return g_utf8_strlen(bubble_get_message_body (bubble), -1);
356
bubble_window_get_character_at_offset (AtkText *obj,
361
const gchar* body_text;
363
g_return_val_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj), 0);
365
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
370
bubble = g_object_get_data (G_OBJECT (widget), "bubble");
372
body_text = bubble_get_message_body (bubble);
374
return g_utf8_get_char (g_utf8_offset_to_pointer (body_text, offset));