~ubuntu-branches/ubuntu/precise/gnome-control-center/precise-updates

« back to all changes in this revision

Viewing changes to typing-break/drw-break-window.c

Tags: upstream-3.0.1.1
ImportĀ upstreamĀ versionĀ 3.0.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
 
/*
3
 
 * Copyright (C) 2002      CodeFactory AB
4
 
 * Copyright (C) 2002-2003 Richard Hult <richard@imendio.com>
5
 
 
6
 
 *
7
 
 * This program is free software; you can redistribute it and/or
8
 
 * modify it under the terms of the GNU General Public License as
9
 
 * published by the Free Software Foundation; either version 2 of the
10
 
 * License, or (at your option) any later version.
11
 
 *
12
 
 * This program is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 
 * General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU General Public
18
 
 * License along with this program; if not, write to the
19
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
 
 * Boston, MA 02111-1307, USA.
21
 
 */
22
 
 
23
 
#include <config.h>
24
 
#include <string.h>
25
 
#include <math.h>
26
 
#include <glib/gi18n.h>
27
 
#include <gtk/gtk.h>
28
 
#include <gdk/gdkkeysyms.h>
29
 
#include <gconf/gconf-client.h>
30
 
 
31
 
#ifdef HAVE_CANBERRA_GTK
32
 
#include <canberra-gtk.h>
33
 
#endif
34
 
 
35
 
#include "drwright.h"
36
 
#include "drw-utils.h"
37
 
#include "drw-break-window.h"
38
 
#include "drw-timer.h"
39
 
 
40
 
struct _DrwBreakWindowPrivate {
41
 
        GtkWidget *clock_label;
42
 
        GtkWidget *break_label;
43
 
        GtkWidget *image;
44
 
 
45
 
        GtkWidget *postpone_entry;
46
 
        GtkWidget *postpone_button;
47
 
 
48
 
        DrwTimer  *timer;
49
 
 
50
 
        gint       break_time;
51
 
        gchar     *break_text;
52
 
        guint      clock_timeout_id;
53
 
        guint      postpone_timeout_id;
54
 
        guint      postpone_sensitize_id;
55
 
};
56
 
 
57
 
#define DRW_BREAK_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DRW_TYPE_BREAK_WINDOW, DrwBreakWindowPrivate))
58
 
 
59
 
#define POSTPONE_CANCEL 30
60
 
 
61
 
/* Signals */
62
 
enum {
63
 
        DONE,
64
 
        POSTPONE,
65
 
        LAST_SIGNAL
66
 
};
67
 
 
68
 
static void         drw_break_window_class_init    (DrwBreakWindowClass *klass);
69
 
static void         drw_break_window_init          (DrwBreakWindow      *window);
70
 
static void         drw_break_window_finalize      (GObject             *object);
71
 
static void         drw_break_window_dispose       (GObject             *object);
72
 
static gboolean     postpone_sensitize_cb          (DrwBreakWindow      *window);
73
 
static gboolean     clock_timeout_cb               (DrwBreakWindow      *window);
74
 
static void         postpone_clicked_cb            (GtkWidget           *button,
75
 
                                                    GtkWidget           *window);
76
 
static gboolean     label_expose_event_cb          (GtkLabel            *label,
77
 
                                                    GdkEventExpose      *event,
78
 
                                                    gpointer             user_data);
79
 
static void         label_size_request_cb          (GtkLabel            *label,
80
 
                                                    GtkRequisition      *requisition,
81
 
                                                    gpointer             user_data);
82
 
 
83
 
G_DEFINE_TYPE (DrwBreakWindow, drw_break_window, GTK_TYPE_WINDOW)
84
 
 
85
 
static guint signals[LAST_SIGNAL];
86
 
 
87
 
static void
88
 
drw_break_window_class_init (DrwBreakWindowClass *klass)
89
 
{
90
 
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
91
 
 
92
 
        object_class->finalize = drw_break_window_finalize;
93
 
        object_class->dispose = drw_break_window_dispose;
94
 
 
95
 
        signals[POSTPONE] =
96
 
                g_signal_new ("postpone",
97
 
                              G_TYPE_FROM_CLASS (klass),
98
 
                              G_SIGNAL_RUN_LAST,
99
 
                              0,
100
 
                              NULL, NULL,
101
 
                              g_cclosure_marshal_VOID__VOID,
102
 
                              G_TYPE_NONE, 0);
103
 
 
104
 
        signals[DONE] =
105
 
                g_signal_new ("done",
106
 
                              G_TYPE_FROM_CLASS (klass),
107
 
                              G_SIGNAL_RUN_LAST,
108
 
                              0,
109
 
                              NULL, NULL,
110
 
                              g_cclosure_marshal_VOID__VOID,
111
 
                              G_TYPE_NONE, 0);
112
 
 
113
 
        g_type_class_add_private (klass, sizeof (DrwBreakWindowPrivate));
114
 
}
115
 
 
116
 
static void
117
 
drw_break_window_init (DrwBreakWindow *window)
118
 
{
119
 
        DrwBreakWindowPrivate *priv;
120
 
        GtkWidget             *vbox;
121
 
        GtkWidget             *hbox;
122
 
        GtkWidget             *align;
123
 
        GtkWidget             *monitor_box;
124
 
        gchar                 *str;
125
 
        GtkWidget             *outer_vbox;
126
 
        GtkWidget             *button_box;
127
 
        gboolean               allow_postpone;
128
 
 
129
 
        gint                   root_monitor = 0;
130
 
        GdkScreen             *screen = NULL;
131
 
        GdkRectangle           monitor;
132
 
        gint                   right_padding;
133
 
        gint                   bottom_padding;
134
 
        GConfClient           *client;
135
 
 
136
 
        priv = DRW_BREAK_WINDOW_GET_PRIVATE (window);
137
 
        window->priv = priv;
138
 
 
139
 
        client = gconf_client_get_default ();
140
 
 
141
 
        priv->break_time = 60 * gconf_client_get_int (client,
142
 
                                                      GCONF_PATH "/break_time",
143
 
                                                      NULL);
144
 
 
145
 
        allow_postpone = gconf_client_get_bool (client,
146
 
                                              GCONF_PATH "/allow_postpone",
147
 
                                              NULL);
148
 
        g_object_unref (client);
149
 
 
150
 
        g_object_set (window, "type", GTK_WINDOW_POPUP, NULL);
151
 
        gtk_window_set_keep_above (GTK_WINDOW (window), TRUE);
152
 
        gtk_window_fullscreen (GTK_WINDOW (window));
153
 
        gtk_window_set_modal (GTK_WINDOW (window), TRUE);
154
 
 
155
 
        screen = gdk_screen_get_default ();
156
 
        gdk_screen_get_monitor_geometry (screen, root_monitor, &monitor);
157
 
 
158
 
        gtk_window_set_default_size (GTK_WINDOW (window),
159
 
                                     gdk_screen_get_width (screen),
160
 
                                     gdk_screen_get_height (screen));
161
 
 
162
 
        gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
163
 
        gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
164
 
        drw_setup_background (GTK_WIDGET (window));
165
 
 
166
 
        align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
167
 
        gtk_widget_show (align);
168
 
 
169
 
        outer_vbox = gtk_vbox_new (FALSE, 0);
170
 
        gtk_widget_show (outer_vbox);
171
 
 
172
 
        right_padding = gdk_screen_get_width (screen) - monitor.width - monitor.x;
173
 
        bottom_padding = gdk_screen_get_height (screen) - monitor.height - monitor.y;
174
 
 
175
 
        monitor_box = gtk_alignment_new (0.5, 0.5, 1, 1);
176
 
        gtk_alignment_set_padding (GTK_ALIGNMENT (monitor_box),
177
 
                                   monitor.y,
178
 
                                   bottom_padding,
179
 
                                   monitor.x,
180
 
                                   right_padding);
181
 
        gtk_widget_show (monitor_box);
182
 
 
183
 
        gtk_container_add (GTK_CONTAINER (window), monitor_box);
184
 
        gtk_container_add (GTK_CONTAINER (monitor_box), outer_vbox);
185
 
 
186
 
        gtk_box_pack_start (GTK_BOX (outer_vbox), align, TRUE, TRUE, 0);
187
 
 
188
 
        if (allow_postpone) {
189
 
                button_box = gtk_hbox_new (FALSE, 0);
190
 
                gtk_widget_show (button_box);
191
 
 
192
 
                gtk_container_set_border_width (GTK_CONTAINER (button_box), 12);
193
 
 
194
 
                priv->postpone_button = gtk_button_new_with_mnemonic (_("_Postpone Break"));
195
 
                gtk_widget_show (priv->postpone_button);
196
 
 
197
 
                gtk_widget_set_sensitive (priv->postpone_button, FALSE);
198
 
 
199
 
                if (priv->postpone_sensitize_id) {
200
 
                        g_source_remove (priv->postpone_sensitize_id);
201
 
                }
202
 
 
203
 
                priv->postpone_sensitize_id = g_timeout_add_seconds (5,
204
 
                                                                     (GSourceFunc) postpone_sensitize_cb,
205
 
                                                                     window);
206
 
 
207
 
                g_signal_connect (priv->postpone_button,
208
 
                                  "clicked",
209
 
                                  G_CALLBACK (postpone_clicked_cb),
210
 
                                  window);
211
 
 
212
 
                gtk_box_pack_end (GTK_BOX (button_box), priv->postpone_button, FALSE, TRUE, 0);
213
 
 
214
 
                priv->postpone_entry = gtk_entry_new ();
215
 
                gtk_entry_set_has_frame (GTK_ENTRY (priv->postpone_entry), FALSE);
216
 
 
217
 
                gtk_box_pack_end (GTK_BOX (button_box), priv->postpone_entry, FALSE, TRUE, 4);
218
 
 
219
 
                gtk_box_pack_end (GTK_BOX (outer_vbox), button_box, FALSE, TRUE, 0);
220
 
        }
221
 
 
222
 
        vbox = gtk_vbox_new (FALSE, 0);
223
 
        gtk_widget_show (vbox);
224
 
 
225
 
        gtk_container_add (GTK_CONTAINER (align), vbox);
226
 
 
227
 
        hbox = gtk_hbox_new (FALSE, 0);
228
 
        gtk_widget_show (hbox);
229
 
        gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
230
 
 
231
 
        priv->image = gtk_image_new_from_stock (GTK_STOCK_STOP, GTK_ICON_SIZE_DIALOG);
232
 
        gtk_misc_set_alignment (GTK_MISC (priv->image), 1, 0.5);
233
 
        gtk_widget_show (priv->image);
234
 
        gtk_box_pack_start (GTK_BOX (hbox), priv->image, TRUE, TRUE, 8);
235
 
 
236
 
        priv->break_label = gtk_label_new (NULL);
237
 
        gtk_widget_show (priv->break_label);
238
 
 
239
 
        g_signal_connect (priv->break_label,
240
 
                          "expose_event",
241
 
                          G_CALLBACK (label_expose_event_cb),
242
 
                          NULL);
243
 
 
244
 
        g_signal_connect_after (priv->break_label,
245
 
                                "size_request",
246
 
                                G_CALLBACK (label_size_request_cb),
247
 
                                NULL);
248
 
 
249
 
        str = g_strdup_printf ("<span size=\"xx-large\" foreground=\"white\"><b>%s</b></span>",
250
 
                               _("Take a break!"));
251
 
        gtk_label_set_markup (GTK_LABEL (priv->break_label), str);
252
 
        g_free (str);
253
 
 
254
 
        gtk_box_pack_start (GTK_BOX (hbox), priv->break_label, FALSE, FALSE, 12);
255
 
 
256
 
 
257
 
        priv->clock_label = gtk_label_new (NULL);
258
 
        gtk_misc_set_alignment (GTK_MISC (priv->clock_label), 0.5, 0.5);
259
 
        gtk_widget_show (priv->clock_label);
260
 
        gtk_box_pack_start (GTK_BOX (vbox), priv->clock_label, TRUE, TRUE, 8);
261
 
 
262
 
        g_signal_connect (priv->clock_label,
263
 
                          "expose_event",
264
 
                          G_CALLBACK (label_expose_event_cb),
265
 
                          NULL);
266
 
 
267
 
        g_signal_connect_after (priv->clock_label,
268
 
                                "size_request",
269
 
                                G_CALLBACK (label_size_request_cb),
270
 
                                NULL);
271
 
 
272
 
        gtk_window_stick (GTK_WINDOW (window));
273
 
 
274
 
        priv->timer = drw_timer_new ();
275
 
 
276
 
        /* Make sure we have a valid time label from the start. */
277
 
        clock_timeout_cb (window);
278
 
 
279
 
        priv->clock_timeout_id = g_timeout_add (1000,
280
 
                                                (GSourceFunc) clock_timeout_cb,
281
 
                                                window);
282
 
#ifdef HAVE_CANBERRA_GTK
283
 
        ca_context_play (ca_gtk_context_get (), 0, CA_PROP_EVENT_ID, "desktop-screen-lock", NULL);
284
 
#endif
285
 
}
286
 
 
287
 
static void
288
 
drw_break_window_finalize (GObject *object)
289
 
{
290
 
        DrwBreakWindow        *window = DRW_BREAK_WINDOW (object);
291
 
        DrwBreakWindowPrivate *priv;
292
 
 
293
 
        priv = window->priv;
294
 
 
295
 
        if (priv->clock_timeout_id != 0) {
296
 
                g_source_remove (priv->clock_timeout_id);
297
 
        }
298
 
 
299
 
        if (priv->postpone_timeout_id != 0) {
300
 
                g_source_remove (priv->postpone_timeout_id);
301
 
        }
302
 
 
303
 
        if (priv->postpone_sensitize_id != 0) {
304
 
                g_source_remove (priv->postpone_sensitize_id);
305
 
        }
306
 
 
307
 
        window->priv = NULL;
308
 
 
309
 
        if (G_OBJECT_CLASS (drw_break_window_parent_class)->finalize) {
310
 
                (* G_OBJECT_CLASS (drw_break_window_parent_class)->finalize) (object);
311
 
        }
312
 
}
313
 
 
314
 
static void
315
 
drw_break_window_dispose (GObject *object)
316
 
{
317
 
        DrwBreakWindow        *window = DRW_BREAK_WINDOW (object);
318
 
        DrwBreakWindowPrivate *priv;
319
 
 
320
 
        priv = window->priv;
321
 
 
322
 
        if (priv->timer) {
323
 
                drw_timer_destroy (priv->timer);
324
 
                priv->timer = NULL;
325
 
        }
326
 
 
327
 
        if (priv->clock_timeout_id != 0) {
328
 
                g_source_remove (priv->clock_timeout_id);
329
 
                priv->clock_timeout_id = 0;
330
 
        }
331
 
 
332
 
        if (priv->postpone_timeout_id != 0) {
333
 
                g_source_remove (priv->postpone_timeout_id);
334
 
                priv->postpone_timeout_id = 0;
335
 
        }
336
 
 
337
 
        if (priv->postpone_sensitize_id != 0) {
338
 
                g_source_remove (priv->postpone_sensitize_id);
339
 
        }
340
 
 
341
 
        if (G_OBJECT_CLASS (drw_break_window_parent_class)->dispose) {
342
 
                (* G_OBJECT_CLASS (drw_break_window_parent_class)->dispose) (object);
343
 
        }
344
 
}
345
 
 
346
 
GtkWidget *
347
 
drw_break_window_new (void)
348
 
{
349
 
        GObject *object;
350
 
 
351
 
        object = g_object_new (DRW_TYPE_BREAK_WINDOW,
352
 
                               "type", GTK_WINDOW_POPUP,
353
 
                               "skip-taskbar-hint", TRUE,
354
 
                               "skip-pager-hint", TRUE,
355
 
                               "focus-on-map", TRUE,
356
 
                               NULL);
357
 
 
358
 
        return GTK_WIDGET (object);
359
 
}
360
 
 
361
 
static gboolean
362
 
postpone_sensitize_cb (DrwBreakWindow *window)
363
 
{
364
 
        DrwBreakWindowPrivate *priv;
365
 
 
366
 
        priv = window->priv;
367
 
 
368
 
        gtk_widget_set_sensitive (priv->postpone_button, TRUE);
369
 
 
370
 
        priv->postpone_sensitize_id = 0;
371
 
        return FALSE;
372
 
}
373
 
 
374
 
static gboolean
375
 
clock_timeout_cb (DrwBreakWindow *window)
376
 
{
377
 
        DrwBreakWindowPrivate *priv;
378
 
        gchar                 *txt;
379
 
        gint                   minutes;
380
 
        gint                   seconds;
381
 
 
382
 
        g_return_val_if_fail (DRW_IS_BREAK_WINDOW (window), FALSE);
383
 
 
384
 
        priv = window->priv;
385
 
 
386
 
        seconds = 1 + priv->break_time - drw_timer_elapsed (priv->timer);
387
 
        seconds = MAX (0, seconds);
388
 
 
389
 
        if (seconds == 0) {
390
 
                /* Zero this out so the finalizer doesn't try to remove the
391
 
                 * source, which would be done in the timeout callback ==
392
 
                 * no-no.
393
 
                 */
394
 
                priv->clock_timeout_id = 0;
395
 
 
396
 
#ifdef HAVE_CANBERRA_GTK
397
 
                ca_context_play (ca_gtk_context_get (), 0, CA_PROP_EVENT_ID, "alarm-clock-elapsed", NULL);
398
 
#endif
399
 
                g_signal_emit (window, signals[DONE], 0, NULL);
400
 
 
401
 
                return FALSE;
402
 
        }
403
 
 
404
 
        minutes = seconds / 60;
405
 
        seconds -= minutes * 60;
406
 
 
407
 
        txt = g_strdup_printf ("<span size=\"25000\" foreground=\"white\"><b>%d:%02d</b></span>",
408
 
                               minutes,
409
 
                               seconds);
410
 
        gtk_label_set_markup (GTK_LABEL (priv->clock_label), txt);
411
 
        g_free (txt);
412
 
 
413
 
        return TRUE;
414
 
}
415
 
 
416
 
static void
417
 
postpone_entry_activate_cb (GtkWidget      *entry,
418
 
                          DrwBreakWindow *window)
419
 
{
420
 
        const gchar *str;
421
 
        gchar *phrase;
422
 
        GConfClient *client = gconf_client_get_default();
423
 
 
424
 
        str = gtk_entry_get_text (GTK_ENTRY (entry));
425
 
 
426
 
        phrase = gconf_client_get_string (client,
427
 
                                          GCONF_PATH "/unlock_phrase",
428
 
                                          NULL);
429
 
        g_object_unref (client);
430
 
 
431
 
        if (!strcmp (str, phrase)) {
432
 
                g_signal_emit (window, signals[POSTPONE], 0, NULL);
433
 
                g_free (phrase);
434
 
                return;
435
 
        }
436
 
 
437
 
        g_free (phrase);
438
 
        gtk_entry_set_text (GTK_ENTRY (entry), "");
439
 
}
440
 
 
441
 
static gboolean
442
 
grab_on_window (GdkWindow *window,
443
 
                guint32    activate_time)
444
 
{
445
 
        if ((gdk_pointer_grab (window, TRUE,
446
 
                               GDK_BUTTON_PRESS_MASK |
447
 
                               GDK_BUTTON_RELEASE_MASK |
448
 
                               GDK_POINTER_MOTION_MASK,
449
 
                               NULL, NULL, activate_time) == 0)) {
450
 
                if (gdk_keyboard_grab (window, TRUE,
451
 
                               activate_time) == 0)
452
 
                        return TRUE;
453
 
                else {
454
 
                        gdk_pointer_ungrab (activate_time);
455
 
                        return FALSE;
456
 
                }
457
 
        }
458
 
 
459
 
        return FALSE;
460
 
}
461
 
 
462
 
static gboolean
463
 
postpone_cancel_cb (DrwBreakWindow *window)
464
 
{
465
 
        DrwBreakWindowPrivate *priv;
466
 
 
467
 
        priv = window->priv;
468
 
 
469
 
        gtk_entry_set_text (GTK_ENTRY (priv->postpone_entry), "");
470
 
        gtk_widget_hide (priv->postpone_entry);
471
 
 
472
 
        priv->postpone_timeout_id = 0;
473
 
 
474
 
        return FALSE;
475
 
}
476
 
 
477
 
static gboolean
478
 
postpone_entry_key_press_event_cb (GtkEntry       *entry,
479
 
                                   GdkEventKey    *event,
480
 
                                   DrwBreakWindow *window)
481
 
{
482
 
        DrwBreakWindowPrivate *priv;
483
 
 
484
 
        priv = window->priv;
485
 
 
486
 
        if (event->keyval == GDK_Escape) {
487
 
                if (priv->postpone_timeout_id) {
488
 
                        g_source_remove (priv->postpone_timeout_id);
489
 
                }
490
 
 
491
 
                postpone_cancel_cb (window);
492
 
 
493
 
                return TRUE;
494
 
        }
495
 
 
496
 
        g_source_remove (priv->postpone_timeout_id);
497
 
 
498
 
        priv->postpone_timeout_id = g_timeout_add_seconds (POSTPONE_CANCEL, (GSourceFunc) postpone_cancel_cb, window);
499
 
 
500
 
        return FALSE;
501
 
}
502
 
 
503
 
static void
504
 
postpone_clicked_cb (GtkWidget *button,
505
 
                     GtkWidget *window)
506
 
{
507
 
        DrwBreakWindow        *bw = DRW_BREAK_WINDOW (window);
508
 
        DrwBreakWindowPrivate *priv = bw->priv;
509
 
        gchar                 *phrase;
510
 
 
511
 
        /* Disable the phrase for now. */
512
 
        phrase = NULL; /*gconf_client_get_string (gconf_client_get_default (),
513
 
                                          GCONF_PATH "/unlock_phrase",
514
 
                                          NULL);*/
515
 
 
516
 
        if (!phrase || !phrase[0]) {
517
 
                g_signal_emit (window, signals[POSTPONE], 0, NULL);
518
 
                return;
519
 
        }
520
 
 
521
 
        if (gtk_widget_get_visible (priv->postpone_entry)) {
522
 
                gtk_widget_activate (priv->postpone_entry);
523
 
                return;
524
 
        }
525
 
 
526
 
        gtk_widget_show (priv->postpone_entry);
527
 
 
528
 
        priv->postpone_timeout_id = g_timeout_add_seconds (POSTPONE_CANCEL, (GSourceFunc) postpone_cancel_cb, bw);
529
 
 
530
 
        grab_on_window (gtk_widget_get_window (priv->postpone_entry),  gtk_get_current_event_time ());
531
 
 
532
 
        gtk_widget_grab_focus (priv->postpone_entry);
533
 
 
534
 
        g_signal_connect (priv->postpone_entry,
535
 
                          "activate",
536
 
                          G_CALLBACK (postpone_entry_activate_cb),
537
 
                          bw);
538
 
 
539
 
        g_signal_connect (priv->postpone_entry,
540
 
                          "key_press_event",
541
 
                          G_CALLBACK (postpone_entry_key_press_event_cb),
542
 
                          bw);
543
 
}
544
 
 
545
 
static void
546
 
get_layout_location (GtkLabel *label,
547
 
                     gint     *xp,
548
 
                     gint     *yp)
549
 
{
550
 
        GtkMisc        *misc;
551
 
        GtkWidget      *widget;
552
 
        GtkAllocation  widget_allocation;
553
 
        GtkRequisition widget_requisition;
554
 
        gfloat         xalign, yalign;
555
 
        gint           x, y;
556
 
        gint           xpad, ypad;
557
 
 
558
 
        misc = GTK_MISC (label);
559
 
        widget = GTK_WIDGET (label);
560
 
 
561
 
        gtk_misc_get_alignment (misc, &xalign, &yalign);
562
 
        gtk_misc_get_padding (misc, &xpad, &ypad);
563
 
        gtk_widget_get_allocation (widget, &widget_allocation);
564
 
        gtk_widget_get_requisition (widget, &widget_requisition);
565
 
 
566
 
        if (gtk_widget_get_direction (widget) != GTK_TEXT_DIR_LTR)
567
 
                xalign = 1.0 - xalign;
568
 
 
569
 
        x = floor (widget_allocation.x + (int)xpad
570
 
                   + ((widget_allocation.width - widget_requisition.width - 1) * xalign)
571
 
                   + 0.5);
572
 
 
573
 
        y = floor (widget_allocation.y + (int)ypad
574
 
                   + ((widget_allocation.height - widget_requisition.height - 1) * yalign)
575
 
                   + 0.5);
576
 
 
577
 
        if (xp) {
578
 
                *xp = x;
579
 
        }
580
 
 
581
 
        if (yp) {
582
 
                *yp = y;
583
 
        }
584
 
}
585
 
 
586
 
static gboolean
587
 
label_expose_event_cb (GtkLabel       *label,
588
 
                       GdkEventExpose *event,
589
 
                       gpointer        user_data)
590
 
{
591
 
        gint       x, y;
592
 
        GdkColor   color;
593
 
        GtkWidget *widget;
594
 
        GdkWindow *window;
595
 
        GdkGC     *gc;
596
 
 
597
 
        color.red = 0;
598
 
        color.green = 0;
599
 
        color.blue = 0;
600
 
        color.pixel = 0;
601
 
 
602
 
        get_layout_location (label, &x, &y);
603
 
 
604
 
        widget = GTK_WIDGET (label);
605
 
        window = gtk_widget_get_window (widget);
606
 
 
607
 
        gc = gdk_gc_new (window);
608
 
        gdk_gc_set_rgb_fg_color (gc, &color);
609
 
        gdk_gc_set_clip_rectangle (gc, &event->area);
610
 
 
611
 
        gdk_draw_layout_with_colors (window,
612
 
                                     gc,
613
 
                                     x + 1,
614
 
                                     y + 1,
615
 
                                     gtk_label_get_layout (label),
616
 
                                     &color,
617
 
                                     NULL);
618
 
        g_object_unref (gc);
619
 
 
620
 
        gtk_paint_layout (gtk_widget_get_style (widget),
621
 
                          window,
622
 
                          gtk_widget_get_state (widget),
623
 
                          FALSE,
624
 
                          &event->area,
625
 
                          widget,
626
 
                          "label",
627
 
                          x, y,
628
 
                          gtk_label_get_layout (label));
629
 
 
630
 
        return TRUE;
631
 
}
632
 
 
633
 
static void
634
 
label_size_request_cb (GtkLabel       *label,
635
 
                       GtkRequisition *requisition,
636
 
                       gpointer        user_data)
637
 
{
638
 
        requisition->width += 1;
639
 
        requisition->height += 1;
640
 
}