~elementary-os/elementaryos/os-patch-notify-osd-precise

« back to all changes in this revision

Viewing changes to src/bubble-window-accessible.c

  • Committer: Sergey "Shnatsel" Davidoff
  • Date: 2012-06-18 21:08:31 UTC
  • Revision ID: shnatsel@gmail.com-20120618210831-g6k5y7vecjdylgic
Initial import, version 0.9.34-0ubuntu2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************************
 
2
**3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
 
3
**      10        20        30        40        50        60        70        80
 
4
**
 
5
** notify-osd
 
6
**
 
7
** bubble-window-accessible.c - implements an accessible bubble window
 
8
**
 
9
** Copyright 2009 Canonical Ltd.
 
10
**
 
11
** Authors:
 
12
**    Eitan Isaacson <eitan@ascender.com>
 
13
**
 
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.
 
17
**
 
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.
 
22
**
 
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/>.
 
25
**
 
26
*******************************************************************************/
 
27
 
 
28
#include "bubble-window-accessible.h"
 
29
#include "bubble.h"
 
30
#include <string.h>
 
31
 
 
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,
 
38
                                                             gpointer                     data);
 
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,
 
42
                                                             GValue*                      value);
 
43
static void        bubble_window_get_maximum_value          (AtkValue*                    obj,
 
44
                                                             GValue*                      value);
 
45
static void        bubble_window_get_minimum_value          (AtkValue*                    obj,
 
46
                                                             GValue*                      value);
 
47
static void        bubble_value_changed_event               (Bubble*                      bubble,
 
48
                                                             gint                         value,
 
49
                                                             AtkObject                   *obj);
 
50
static void        bubble_message_body_deleted_event        (Bubble*                      bubble,
 
51
                                                             const gchar*                 text,
 
52
                                                             AtkObject*                   obj);
 
53
static void        bubble_message_body_inserted_event       (Bubble*                      bubble,
 
54
                                                             const gchar*                 text,
 
55
                                                             AtkObject*                   obj);
 
56
 
 
57
static gchar*      bubble_window_get_text                   (AtkText                     *obj,
 
58
                                                                                                                         gint                         start_offset,
 
59
                                                                                                                         gint                         end_offset);
 
60
static gint        bubble_window_get_character_count        (AtkText                     *obj);
 
61
static gunichar    bubble_window_get_character_at_offset    (AtkText                     *obj,
 
62
                                                             gint                         offset);
 
63
 
 
64
static void* bubble_window_accessible_parent_class;
 
65
 
 
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))
 
69
 
 
70
static void
 
71
atk_value_interface_init (AtkValueIface* iface)
 
72
{
 
73
    g_return_if_fail (iface != NULL);
 
74
    
 
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;
 
78
}
 
79
 
 
80
static void
 
81
atk_text_interface_init (AtkTextIface* iface)
 
82
{
 
83
    g_return_if_fail (iface != NULL);
 
84
 
 
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;
 
88
 
 
89
}
 
90
 
 
91
static void
 
92
bubble_window_accessible_init (BubbleWindowAccessible *object)
 
93
{
 
94
        /* TODO: Add initialization code here */
 
95
}
 
96
 
 
97
static void
 
98
bubble_window_accessible_finalize (GObject *object)
 
99
{
 
100
        /* TODO: Add deinitalization code here */
 
101
 
 
102
        G_OBJECT_CLASS (bubble_window_accessible_parent_class)->finalize (object);
 
103
}
 
104
 
 
105
static void
 
106
bubble_window_accessible_class_init (BubbleWindowAccessibleClass *klass)
 
107
{
 
108
        GObjectClass*   object_class = G_OBJECT_CLASS (klass);
 
109
        AtkObjectClass* class        = ATK_OBJECT_CLASS (klass);
 
110
    
 
111
    bubble_window_accessible_parent_class = g_type_class_peek_parent (klass);
 
112
    
 
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;
 
116
 
 
117
        object_class->finalize = bubble_window_accessible_finalize;
 
118
}
 
119
 
 
120
static void
 
121
bubble_window_real_initialize (AtkObject* obj,
 
122
                               gpointer   data)
 
123
{
 
124
    GtkWidget* widget = GTK_WIDGET (data);
 
125
    Bubble*    bubble; 
 
126
 
 
127
    ATK_OBJECT_CLASS (bubble_window_accessible_parent_class)->initialize (obj, data);
 
128
 
 
129
    bubble = g_object_get_data (G_OBJECT(widget), "bubble");
 
130
    
 
131
    g_signal_connect (bubble,
 
132
                      "value-changed",
 
133
                      G_CALLBACK (bubble_value_changed_event),
 
134
                      obj);
 
135
 
 
136
    g_signal_connect (bubble,
 
137
                      "message-body-deleted",
 
138
                      G_CALLBACK (bubble_message_body_deleted_event),
 
139
                      obj);
 
140
 
 
141
    g_signal_connect (bubble,
 
142
                      "message-body-inserted",
 
143
                      G_CALLBACK (bubble_message_body_inserted_event),
 
144
                      obj);
 
145
 
 
146
    atk_object_set_role (obj, ATK_ROLE_NOTIFICATION);
 
147
}
 
148
 
 
149
AtkObject*
 
150
bubble_window_accessible_new (GtkWidget *widget)
 
151
{
 
152
        GObject       *object;
 
153
        AtkObject     *aobj;
 
154
        
 
155
        object = g_object_new (BUBBLE_WINDOW_TYPE_ACCESSIBLE, NULL);
 
156
        
 
157
        aobj = ATK_OBJECT (object);
 
158
        
 
159
        gtk_accessible_set_widget (GTK_ACCESSIBLE (aobj), widget);
 
160
        
 
161
        atk_object_initialize (aobj, widget);
 
162
        
 
163
        return aobj;
 
164
}
 
165
 
 
166
static const char* 
 
167
bubble_window_accessible_get_name (AtkObject* obj)
 
168
{
 
169
        GtkWidget*     widget;
 
170
        Bubble*        bubble;
 
171
    const gchar*   title;
 
172
 
 
173
        g_return_val_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj), "");
 
174
        
 
175
        widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
 
176
    
 
177
        if (widget == NULL)
 
178
                return "";
 
179
        
 
180
        bubble = g_object_get_data (G_OBJECT (widget), "bubble");
 
181
 
 
182
    g_return_val_if_fail (IS_BUBBLE (bubble), "");
 
183
    
 
184
    
 
185
    title = bubble_get_title(bubble);
 
186
    if (g_strcmp0(title, " ") == 0)
 
187
    {
 
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)
 
193
            return synch_str;
 
194
        else
 
195
            return "";
 
196
    } 
 
197
    
 
198
    
 
199
    return title;
 
200
}
 
201
 
 
202
static const char*
 
203
bubble_window_accessible_get_description (AtkObject* obj)
 
204
{
 
205
        GtkWidget     *widget;
 
206
        Bubble        *bubble;
 
207
 
 
208
        g_return_val_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj), "");
 
209
        
 
210
        widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
 
211
    
 
212
        if (widget == NULL)
 
213
                return "";
 
214
        
 
215
        bubble = g_object_get_data (G_OBJECT (widget), "bubble");
 
216
 
 
217
    g_return_val_if_fail (IS_BUBBLE (bubble), "");
 
218
    
 
219
    return bubble_get_message_body(bubble);
 
220
}
 
221
 
 
222
static void      
 
223
bubble_window_get_current_value (AtkValue* obj,
 
224
                                 GValue*   value)
 
225
{
 
226
    gdouble        current_value;
 
227
        GtkWidget*     widget;
 
228
        Bubble*        bubble;
 
229
 
 
230
        g_return_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj));
 
231
        
 
232
        widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
 
233
    
 
234
        if (widget == NULL)
 
235
                return;
 
236
        
 
237
        bubble = g_object_get_data (G_OBJECT (widget), "bubble");
 
238
 
 
239
    current_value = (gdouble) bubble_get_value(bubble);
 
240
    
 
241
    memset (value,  0, sizeof (GValue));
 
242
    g_value_init (value, G_TYPE_DOUBLE);
 
243
    g_value_set_double (value,current_value);
 
244
}
 
245
 
 
246
static void      
 
247
bubble_window_get_maximum_value (AtkValue* obj,
 
248
                                 GValue*   value)
 
249
{
 
250
    memset (value,  0, sizeof (GValue));
 
251
    g_value_init (value, G_TYPE_DOUBLE);
 
252
    g_value_set_double (value, 100.0);
 
253
}
 
254
 
 
255
static void      
 
256
bubble_window_get_minimum_value (AtkValue* obj,
 
257
                                 GValue*   value)
 
258
{
 
259
    memset (value,  0, sizeof (GValue));
 
260
    g_value_init (value, G_TYPE_DOUBLE);
 
261
    g_value_set_double (value, 0.0);
 
262
}
 
263
 
 
264
static void
 
265
bubble_value_changed_event (Bubble*    bubble,
 
266
                            gint       value,
 
267
                            AtkObject* obj)
 
268
{
 
269
    g_object_notify (G_OBJECT (obj), "accessible-value");
 
270
}
 
271
 
 
272
static void
 
273
bubble_message_body_deleted_event (Bubble*      bubble,
 
274
                                   const gchar* text,
 
275
                                   AtkObject*   obj)
 
276
{
 
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));    
 
280
}
 
281
 
 
282
static void
 
283
bubble_message_body_inserted_event (Bubble*      bubble,
 
284
                                  const gchar* text,
 
285
                                  AtkObject*   obj)
 
286
{
 
287
    const gchar* message_body;
 
288
 
 
289
    message_body = bubble_get_message_body (bubble);
 
290
 
 
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));    
 
295
}
 
296
 
 
297
static gchar*
 
298
bubble_window_get_text (AtkText *obj,
 
299
                                                gint    start_offset,
 
300
                                                gint    end_offset)
 
301
{
 
302
        GtkWidget*     widget;
 
303
        Bubble*        bubble;
 
304
        const gchar*   body_text;
 
305
    gsize          char_length;
 
306
        glong          body_strlen;
 
307
 
 
308
        g_return_val_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj), g_strdup(""));
 
309
 
 
310
        widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
 
311
 
 
312
        g_return_val_if_fail (GTK_IS_WINDOW (widget), g_strdup(""));
 
313
        
 
314
        bubble = g_object_get_data (G_OBJECT(widget), "bubble");
 
315
 
 
316
        if (end_offset <= start_offset)
 
317
                return g_strdup("");
 
318
 
 
319
        body_text = bubble_get_message_body (bubble);
 
320
 
 
321
        body_strlen = g_utf8_strlen(body_text, -1);
 
322
 
 
323
        if (start_offset > body_strlen)
 
324
                start_offset = body_strlen;
 
325
 
 
326
        if (end_offset > body_strlen || end_offset == -1)
 
327
                end_offset = body_strlen;
 
328
 
 
329
 
 
330
    char_length = g_utf8_offset_to_pointer (body_text, end_offset) - 
 
331
        g_utf8_offset_to_pointer (body_text, start_offset);
 
332
    
 
333
        return g_strndup (g_utf8_offset_to_pointer(body_text, start_offset), 
 
334
                                          char_length);
 
335
}
 
336
 
 
337
static gint
 
338
bubble_window_get_character_count (AtkText *obj)
 
339
{
 
340
        GtkWidget*     widget;
 
341
        Bubble*        bubble;
 
342
 
 
343
        g_return_val_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj), 0);
 
344
        
 
345
        widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
 
346
    
 
347
        if (widget == NULL)
 
348
                return 0;
 
349
        
 
350
        bubble = g_object_get_data (G_OBJECT (widget), "bubble");
 
351
 
 
352
        return g_utf8_strlen(bubble_get_message_body (bubble), -1);
 
353
}
 
354
 
 
355
static gunichar
 
356
bubble_window_get_character_at_offset (AtkText *obj,
 
357
                                       gint    offset)
 
358
{
 
359
        GtkWidget*     widget;
 
360
        Bubble*        bubble;
 
361
    const gchar*   body_text;
 
362
 
 
363
        g_return_val_if_fail (BUBBLE_WINDOW_IS_ACCESSIBLE (obj), 0);
 
364
        
 
365
        widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
 
366
    
 
367
        if (widget == NULL)
 
368
                return 0;
 
369
        
 
370
        bubble = g_object_get_data (G_OBJECT (widget), "bubble");
 
371
 
 
372
        body_text = bubble_get_message_body (bubble);
 
373
 
 
374
    return g_utf8_get_char (g_utf8_offset_to_pointer (body_text, offset));
 
375
}