1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2016 Maxime DOYEN
4 * This file is part of HomeBank.
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include <gdk/gdkkeysyms.h>
27 #include "gtk-dateentry.h"
46 static void gtk_date_entry_dispose (GObject
*gobject
);
47 static void gtk_date_entry_finalize (GObject
*gobject
);
48 static void gtk_date_entry_destroy (GtkWidget
*dateentry
);
50 static void gtk_date_entry_entry_activate(GtkWidget
* calendar
, gpointer user_data
);
51 static gint
gtk_date_entry_entry_key_pressed (GtkWidget
*widget
, GdkEventKey
*event
, gpointer user_data
);
52 static void gtk_date_entry_button_clicked (GtkWidget
* widget
, GtkDateEntry
* dateentry
);
55 gtk_date_entry_popup(GtkDateEntry
* dateentry
, GdkEvent
*event
);
57 static gint
gtk_date_entry_popup_key_event (GtkWidget
*widget
, GdkEventKey
*event
, gpointer user_data
);
58 static gint
gtk_date_entry_popup_button_press (GtkWidget
* widget
, GdkEvent
* event
, gpointer data
);
60 static void gtk_date_entry_calendar_year(GtkWidget
* calendar
, GtkDateEntry
* dateentry
);
61 static void gtk_date_entry_calendar_getfrom(GtkWidget
* calendar
, GtkDateEntry
* dateentry
);
62 static gint
gtk_date_entry_calendar_select(GtkWidget
* calendar
, gpointer user_data
);
65 static void gtk_date_entry_entry_set_text(GtkDateEntry
* dateentry
);
66 static void gtk_date_entry_popdown(GtkDateEntry
*dateentry
);
70 static guint dateentry_signals
[LAST_SIGNAL
] = {0,};
74 // this is to be able to seizure d or d/m or m/d in the gtkdateentry
76 /* order of these in the current locale */
77 static GDateDMY dmy_order
[3] =
79 G_DATE_DAY
, G_DATE_MONTH
, G_DATE_YEAR
82 struct _GDateParseTokens
{
88 typedef struct _GDateParseTokens GDateParseTokens
;
93 hb_date_fill_parse_tokens (const gchar
*str
, GDateParseTokens
*pt
)
95 gchar num
[4][NUM_LEN
+1];
99 DB( g_print("\n[dateentry] fill parse token\n") );
101 /* We count 4, but store 3; so we can give an error
104 num
[0][0] = num
[1][0] = num
[2][0] = num
[3][0] = '\0';
106 s
= (const guchar
*) str
;
108 while (*s
&& pt
->num_ints
< 4)
112 while (*s
&& g_ascii_isdigit (*s
) && i
< NUM_LEN
)
114 num
[pt
->num_ints
][i
] = *s
;
121 num
[pt
->num_ints
][i
] = '\0';
125 if (*s
== '\0') break;
130 pt
->n
[0] = pt
->num_ints
> 0 ? atoi (num
[0]) : 0;
131 pt
->n
[1] = pt
->num_ints
> 1 ? atoi (num
[1]) : 0;
132 pt
->n
[2] = pt
->num_ints
> 2 ? atoi (num
[2]) : 0;
138 static void hb_date_determine_dmy(void)
142 GDateParseTokens testpt;
145 DB( g_print("\n[dateentry] determine dmy\n") );
147 g_date_clear (&d, 1); // clear for scratch use
149 // had to pick a random day - don't change this, some strftimes
150 // are broken on some days, and this one is good so far.
151 g_date_set_dmy (&d, 4, 7, 1976);
152 g_date_strftime (buf, 127, "%x", &d);
154 hb_date_fill_parse_tokens (buf, &testpt);
157 while (i < testpt.num_ints)
162 dmy_order[i] = G_DATE_MONTH;
165 dmy_order[i] = G_DATE_DAY;
168 dmy_order[2] = G_DATE_YEAR;
174 DB( g_print(" dmy legend: 0=day, 1=month, 2=year\n") );
175 DB( g_print(" dmy is: %d %d %d\n", dmy_order[0], dmy_order[1], dmy_order[2]) );
179 static void hb_date_parse_tokens(GtkWidget
*gtkentry
, gpointer user_data
)
181 GtkDateEntry
*dateentry
= user_data
;
182 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
186 str
= gtk_entry_get_text (GTK_ENTRY (priv
->entry
));
188 hb_date_fill_parse_tokens(str
, &pt
);
189 DB( g_print(" -> parsetoken return is %d values :%d %d %d\n", pt
.num_ints
, pt
.n
[0], pt
.n
[1], pt
.n
[2]) );
191 // initialize with today's date
192 g_date_set_time_t(priv
->date
, time(NULL
));
194 switch( pt
.num_ints
)
197 DB( g_print(" -> seizured 1 number\n") );
198 if(g_date_valid_day(pt
.n
[0]))
199 g_date_set_day(priv
->date
, pt
.n
[0]);
202 DB( g_print(" -> seizured 2 numbers\n") );
203 if( dmy_order
[0] != G_DATE_YEAR
)
205 if( dmy_order
[0] == G_DATE_DAY
)
207 if(g_date_valid_day(pt
.n
[0]))
208 g_date_set_day(priv
->date
, pt
.n
[0]);
209 if(g_date_valid_month(pt
.n
[1]))
210 g_date_set_month(priv
->date
, pt
.n
[1]);
214 if(g_date_valid_day(pt
.n
[1]))
215 g_date_set_day(priv
->date
, pt
.n
[1]);
216 if(g_date_valid_month(pt
.n
[0]))
217 g_date_set_month(priv
->date
, pt
.n
[0]);
234 G_DEFINE_TYPE(GtkDateEntry
, gtk_date_entry
, GTK_TYPE_BOX
)
239 gtk_date_entry_class_init (GtkDateEntryClass
*class)
241 GObjectClass
*object_class
;
242 GtkWidgetClass
*widget_class
;
244 object_class
= G_OBJECT_CLASS (class);
245 widget_class
= GTK_WIDGET_CLASS (class);
247 DB( g_print("\n[dateentry] class_init\n") );
249 //object_class->constructor = gtk_date_entry_constructor;
250 //object_class->set_property = gtk_date_entry_set_property;
251 //object_class->get_property = gtk_date_entry_get_property;
252 object_class
->dispose
= gtk_date_entry_dispose
;
253 object_class
->finalize
= gtk_date_entry_finalize
;
255 widget_class
->destroy
= gtk_date_entry_destroy
;
257 dateentry_signals
[CHANGED
] =
258 g_signal_new ("changed",
259 G_TYPE_FROM_CLASS (class),
261 G_STRUCT_OFFSET (GtkDateEntryClass
, changed
),
263 g_cclosure_marshal_VOID__VOID
,
266 g_type_class_add_private (object_class
, sizeof (GtkDateEntryPrivate
));
272 gtk_date_entry_entry_focus_out(GtkWidget
*widget
, GdkEventFocus
*event
, gpointer user_data
)
274 GtkDateEntry
*dateentry
= user_data
;
276 DB( g_print("\n[dateentry] entry focus-out-event %d\n", gtk_widget_is_focus(GTK_WIDGET(dateentry
))) );
278 gtk_date_entry_entry_activate(GTK_WIDGET(dateentry
), dateentry
);
284 gtk_date_entry_init (GtkDateEntry
*dateentry
)
286 GtkDateEntryPrivate
*priv
;
288 DB( g_print("\n[dateentry] init\n") );
290 /* yes, also priv, need to keep the code readable */
291 dateentry
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (dateentry
,
293 GtkDateEntryPrivate
);
294 priv
= dateentry
->priv
;
297 /* initialize datas */
298 priv
->date
= g_date_new();
300 priv
->popup_in_progress
= FALSE
;
301 priv
->has_grab
= FALSE
;
303 g_date_set_time_t(priv
->date
, time(NULL
));
305 g_date_set_dmy(&priv
->mindate
, 1, 1, 1900);
306 g_date_set_dmy(&priv
->maxdate
, 31, 12, 2200);
309 gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(dateentry
)), GTK_STYLE_CLASS_LINKED
);
311 //widget=GTK_WIDGET(dateentry);
313 priv
->entry
= gtk_entry_new ();
315 //gtk_entry_set_width_chars(GTK_ENTRY(priv->entry), 10);
316 //gtk_entry_set_max_width_chars(GTK_ENTRY(priv->entry), 4);
319 gtk_box_pack_start (GTK_BOX (dateentry
), priv
->entry
, TRUE
, TRUE
, 0);
321 g_signal_connect (priv
->entry
, "key-press-event",
322 G_CALLBACK (gtk_date_entry_entry_key_pressed
), dateentry
);
324 g_signal_connect_after (priv
->entry
, "focus-out-event",
325 G_CALLBACK (gtk_date_entry_entry_focus_out
), dateentry
);
327 g_signal_connect (priv
->entry
, "activate",
328 G_CALLBACK (gtk_date_entry_entry_activate
), dateentry
);
331 priv
->button
= gtk_button_new ();
332 priv
->arrow
= gtk_image_new_from_icon_name ("pan-down-symbolic", GTK_ICON_SIZE_BUTTON
);
333 gtk_container_add (GTK_CONTAINER (priv
->button
), priv
->arrow
);
334 gtk_box_pack_end (GTK_BOX (dateentry
), priv
->button
, FALSE
, FALSE
, 0);
335 gtk_widget_show_all (priv
->button
);
337 g_signal_connect (priv
->button
, "clicked",
338 G_CALLBACK (gtk_date_entry_button_clicked
), dateentry
);
341 priv
->popup_window
= gtk_window_new (GTK_WINDOW_POPUP
);
342 gtk_window_set_type_hint (
343 GTK_WINDOW (priv
->popup_window
), GDK_WINDOW_TYPE_HINT_COMBO
);
344 gtk_widget_set_events (priv
->popup_window
,
345 gtk_widget_get_events(priv
->popup_window
) | GDK_KEY_PRESS_MASK
);
347 priv
->frame
= gtk_frame_new (NULL
);
348 gtk_container_add (GTK_CONTAINER (priv
->popup_window
), priv
->frame
);
349 gtk_frame_set_shadow_type (GTK_FRAME (priv
->frame
), GTK_SHADOW_ETCHED_IN
);
350 gtk_widget_show (priv
->frame
);
352 g_signal_connect (priv
->popup_window
, "key-press-event",
353 G_CALLBACK (gtk_date_entry_popup_key_event
), dateentry
);
355 g_signal_connect (priv
->popup_window
, "button-press-event",
356 G_CALLBACK (gtk_date_entry_popup_button_press
), dateentry
);
359 priv
->calendar
= gtk_calendar_new ();
360 gtk_container_add (GTK_CONTAINER (priv
->frame
), priv
->calendar
);
361 gtk_widget_show (priv
->calendar
);
363 g_signal_connect (priv
->calendar
, "prev-year",
364 G_CALLBACK (gtk_date_entry_calendar_year
), dateentry
);
365 g_signal_connect (priv
->calendar
, "next-year",
366 G_CALLBACK (gtk_date_entry_calendar_year
), dateentry
);
367 g_signal_connect (priv
->calendar
, "prev-month",
368 G_CALLBACK (gtk_date_entry_calendar_year
), dateentry
);
369 g_signal_connect (priv
->calendar
, "next-month",
370 G_CALLBACK (gtk_date_entry_calendar_year
), dateentry
);
372 g_signal_connect (priv
->calendar
, "day-selected",
373 G_CALLBACK (gtk_date_entry_calendar_getfrom
), dateentry
);
375 g_signal_connect (priv
->calendar
, "day-selected-double-click",
376 G_CALLBACK (gtk_date_entry_calendar_select
), dateentry
);
382 gtk_date_entry_new ()
384 GtkDateEntry
*dateentry
;
386 DB( g_print("\n[dateentry] new\n") );
388 dateentry
= g_object_new (GTK_TYPE_DATE_ENTRY
, NULL
);
390 return GTK_WIDGET(dateentry
);
395 gtk_date_entry_destroy (GtkWidget
*object
)
397 GtkDateEntry
*dateentry
= GTK_DATE_ENTRY (object
);
398 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
400 g_return_if_fail(object
!= NULL
);
401 g_return_if_fail(GTK_IS_DATE_ENTRY(object
));
403 DB( g_print(" \n[dateentry] destroy\n") );
405 DB( g_print(" free gtkentry: %p\n", priv
->entry
) );
406 DB( g_print(" free arrow: %p\n", priv
->button
) );
407 DB( g_print(" free popup_window: %p\n", priv
->popup_window
) );
409 DB( g_print(" free dateentry: %p\n", dateentry
) );
411 if(priv
->popup_window
)
412 gtk_widget_destroy (priv
->popup_window
);
413 priv
->popup_window
= NULL
;
416 g_date_free(priv
->date
);
419 GTK_WIDGET_CLASS (gtk_date_entry_parent_class
)->destroy (object
);
425 gtk_date_entry_dispose (GObject
*gobject
)
427 //GtkDateEntry *self = GTK_DATE_ENTRY (gobject);
429 DB( g_print(" \n[dateentry] dispose\n") );
432 //g_clear_object (&self->priv->an_object);
434 G_OBJECT_CLASS (gtk_date_entry_parent_class
)->dispose (gobject
);
441 gtk_date_entry_finalize (GObject
*gobject
)
443 //GtkDateEntry *self = GTK_DATE_ENTRY (gobject);
445 DB( g_print(" \n[dateentry] finalize\n") );
448 //g_date_free(self->date);
449 //g_free (self->priv->a_string);
451 /* Always chain up to the parent class; as with dispose(), finalize()
452 * is guaranteed to exist on the parent's class virtual function table
454 G_OBJECT_CLASS(gtk_date_entry_parent_class
)->finalize (gobject
);
461 void gtk_date_entry_set_date(GtkDateEntry
*dateentry
, guint32 julian_days
)
463 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
465 DB( g_print(" \n[dateentry] set date\n") );
467 g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry
));
469 if(g_date_valid_julian(julian_days
))
471 g_date_set_julian (priv
->date
, julian_days
);
475 g_date_set_time_t(priv
->date
, time(NULL
));
477 gtk_date_entry_entry_set_text(dateentry
);
483 void gtk_date_entry_set_mindate(GtkDateEntry
*dateentry
, guint32 julian_days
)
485 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
487 DB( g_print(" \n[dateentry] set mindate\n") );
489 g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry
));
491 if(g_date_valid_julian(julian_days
))
493 g_date_set_julian (&priv
->mindate
, julian_days
);
501 void gtk_date_entry_set_maxdate(GtkDateEntry
*dateentry
, guint32 julian_days
)
503 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
505 DB( g_print(" \n[dateentry] set maxdate\n") );
507 g_return_if_fail (GTK_IS_DATE_ENTRY (dateentry
));
509 if(g_date_valid_julian(julian_days
))
511 g_date_set_julian (&priv
->maxdate
, julian_days
);
516 guint32
gtk_date_entry_get_date(GtkDateEntry
* dateentry
)
518 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
520 DB( g_print(" \n[dateentry] get date\n") );
522 g_return_val_if_fail (GTK_IS_DATE_ENTRY (dateentry
), 0);
524 return(g_date_get_julian(priv
->date
));
529 gtk_date_entry_entry_set_text(GtkDateEntry
* dateentry
)
531 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
534 DB( g_print("\n[dateentry] entry set text\n") );
536 g_date_clamp(priv
->date
, &priv
->mindate
, &priv
->maxdate
);
539 if(g_date_valid(priv
->date
) == TRUE
)
541 g_date_strftime (buffer
, 256 - 1, "%x", priv
->date
);
542 gtk_entry_set_text (GTK_ENTRY (priv
->entry
), buffer
);
544 DB( g_print(" = %s\n", buffer
) );
547 gtk_entry_set_text (GTK_ENTRY (priv
->entry
), "??");
550 /* emit the signal */
551 if(priv
->lastdate
!= g_date_get_julian(priv
->date
))
553 DB( g_print(" **emit 'changed' signal**\n") );
555 g_signal_emit_by_name (dateentry
, "changed", NULL
, NULL
);
558 priv
->lastdate
= g_date_get_julian(priv
->date
);
564 gtk_date_entry_entry_activate(GtkWidget
*gtkentry
, gpointer user_data
)
566 GtkDateEntry
*dateentry
= user_data
;
567 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
570 DB( g_print("\n[dateentry] entry_activate\n") );
572 str
= gtk_entry_get_text (GTK_ENTRY (priv
->entry
));
574 //1) we parse the string according to the locale
575 g_date_set_parse (priv
->date
, str
);
576 if(g_date_valid(priv
->date
) == FALSE
)
578 //2) give a try to tokens: day, day/month, month/day
579 hb_date_parse_tokens(gtkentry
, user_data
);
582 //3) at last if date still invalid, put today's dateentry_signals
583 // we should consider just warn the user here
584 if(g_date_valid(priv
->date
) == FALSE
)
587 g_date_set_time_t(priv
->date
, time(NULL
));
590 gtk_date_entry_entry_set_text(dateentry
);
596 gtk_date_entry_calendar_year(GtkWidget
*calendar
, GtkDateEntry
*dateentry
)
598 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
599 guint year
, month
, day
;
601 DB( g_print(" (dateentry) year changed\n") );
603 gtk_calendar_get_date (GTK_CALENDAR (priv
->calendar
), &year
, &month
, &day
);
605 g_object_set(calendar
, "year", 1900, NULL
);
608 g_object_set(calendar
, "year", 2200, NULL
);
614 gtk_date_entry_calendar_getfrom(GtkWidget
* calendar
, GtkDateEntry
* dateentry
)
616 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
617 guint year
, month
, day
;
619 DB( g_print(" (dateentry) calendar_getfrom\n") );
621 gtk_calendar_get_date (GTK_CALENDAR (priv
->calendar
), &year
, &month
, &day
);
622 g_date_set_dmy (priv
->date
, day
, month
+ 1, year
);
623 gtk_date_entry_entry_set_text(dateentry
);
628 gtk_date_entry_calendar_select(GtkWidget
* calendar
, gpointer user_data
)
630 GtkDateEntry
*dateentry
= user_data
;
632 DB( g_print(" (dateentry) calendar_select\n") );
634 gtk_date_entry_calendar_getfrom(NULL
, dateentry
);
636 gtk_date_entry_popdown(dateentry
);
642 gtk_date_entry_entry_key_pressed (GtkWidget
*widget
, GdkEventKey
*event
, gpointer user_data
)
644 GtkDateEntry
*dateentry
= user_data
;
645 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
647 DB( g_print("\n[dateentry] entry key pressed: state=%04x, keyval=%04x\n", event
->state
, event
->keyval
) );
649 if( event
->keyval
== GDK_KEY_Up
)
651 if( !(event
->state
& (GDK_SHIFT_MASK
| GDK_CONTROL_MASK
)) )
653 g_date_add_days (priv
->date
, 1);
654 gtk_date_entry_entry_set_text(dateentry
);
657 if( event
->state
& GDK_SHIFT_MASK
)
659 g_date_add_months (priv
->date
, 1);
660 gtk_date_entry_entry_set_text(dateentry
);
663 if( event
->state
& GDK_CONTROL_MASK
)
665 g_date_add_years (priv
->date
, 1);
666 gtk_date_entry_entry_set_text(dateentry
);
671 if( event
->keyval
== GDK_KEY_Down
)
673 if( !(event
->state
& (GDK_SHIFT_MASK
| GDK_CONTROL_MASK
)) )
675 g_date_subtract_days (priv
->date
, 1);
676 gtk_date_entry_entry_set_text(dateentry
);
679 if( event
->state
& GDK_SHIFT_MASK
)
681 g_date_subtract_months (priv
->date
, 1);
682 gtk_date_entry_entry_set_text(dateentry
);
685 if( event
->state
& GDK_CONTROL_MASK
)
687 g_date_subtract_years (priv
->date
, 1);
688 gtk_date_entry_entry_set_text(dateentry
);
698 gtk_date_entry_popup_position (GtkDateEntry
* dateentry
)
700 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
702 gint bwidth
, bheight
;
704 GdkWindow
*gdkwindow
;
705 GtkAllocation allocation
;
707 DB( g_print("\n[dateentry] position popup\n") );
709 gtk_widget_get_preferred_size (priv
->popup_window
, NULL
, &req
);
711 gdkwindow
= gtk_widget_get_window(priv
->button
);
712 gdk_window_get_origin (gdkwindow
, &x
, &y
);
714 gtk_widget_get_allocation(priv
->button
, &allocation
);
717 bwidth
= allocation
.width
;
718 bheight
= allocation
.height
;
720 x
+= bwidth
- req
.width
;
729 gtk_window_move (GTK_WINDOW (priv
->popup_window
), x
, y
);
734 gtk_date_entry_button_clicked (GtkWidget
* widget
, GtkDateEntry
* dateentry
)
738 DB( g_print("\n[dateentry] button_clicked\n") );
740 /* Obtain the GdkEvent that triggered
741 * the date button's "clicked" signal. */
742 event
= gtk_get_current_event ();
744 gtk_date_entry_popup(dateentry
, event
);
750 gtk_date_entry_popup(GtkDateEntry
* dateentry
, GdkEvent
*event
)
752 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
755 GdkDevice
*event_device
;
756 GdkDevice
*assoc_device
;
757 GdkDevice
*keyboard_device
;
758 GdkDevice
*pointer_device
;
760 GdkGrabStatus grab_status
;
764 DB( g_print("\n[dateentry] popup_display\n****\n\n") );
767 str
= gtk_entry_get_text (GTK_ENTRY (priv
->entry
));
768 g_date_set_parse (priv
->date
, str
);
770 if(g_date_valid(priv
->date
) == TRUE
)
772 /* GtkCalendar expects month to be in 0-11 range (inclusive) */
773 month
= g_date_get_month (priv
->date
) - 1;
774 gtk_calendar_select_month (GTK_CALENDAR (priv
->calendar
),
775 CLAMP (month
, 0, 11),
776 g_date_get_year (priv
->date
));
777 gtk_calendar_select_day (GTK_CALENDAR (priv
->calendar
),
778 g_date_get_day (priv
->date
));
783 gtk_date_entry_popup_position(dateentry
);
784 gtk_widget_show (priv
->popup_window
);
785 gtk_widget_grab_focus (priv
->popup_window
);
786 gtk_grab_add (priv
->popup_window
);
788 window
= gtk_widget_get_window (priv
->popup_window
);
790 g_return_if_fail (priv
->grab_keyboard
== NULL
);
791 g_return_if_fail (priv
->grab_pointer
== NULL
);
793 event_device
= gdk_event_get_device (event
);
794 assoc_device
= gdk_device_get_associated_device (event_device
);
796 event_time
= gdk_event_get_time (event
);
798 if (gdk_device_get_source (event_device
) == GDK_SOURCE_KEYBOARD
) {
799 keyboard_device
= event_device
;
800 pointer_device
= assoc_device
;
802 keyboard_device
= assoc_device
;
803 pointer_device
= event_device
;
806 if (keyboard_device
!= NULL
) {
807 grab_status
= gdk_device_grab (
810 GDK_OWNERSHIP_WINDOW
,
813 GDK_KEY_RELEASE_MASK
,
816 if (grab_status
== GDK_GRAB_SUCCESS
) {
817 priv
->grab_keyboard
=
818 g_object_ref (keyboard_device
);
822 if (pointer_device
!= NULL
) {
823 grab_status
= gdk_device_grab (
826 GDK_OWNERSHIP_WINDOW
,
828 GDK_BUTTON_PRESS_MASK
|
829 GDK_BUTTON_RELEASE_MASK
|
830 GDK_POINTER_MOTION_MASK
,
833 if (grab_status
== GDK_GRAB_SUCCESS
) {
835 g_object_ref (pointer_device
);
836 } else if (priv
->grab_keyboard
!= NULL
) {
840 g_object_unref (priv
->grab_keyboard
);
841 priv
->grab_keyboard
= NULL
;
845 gdk_window_focus (window
, event_time
);
851 gtk_date_entry_popdown(GtkDateEntry
*dateentry
)
853 GtkDateEntryPrivate
*priv
= dateentry
->priv
;
855 DB( g_print("\n[dateentry] popdown\n") );
857 gtk_widget_hide (priv
->popup_window
);
858 gtk_grab_remove (priv
->popup_window
);
860 if (priv
->grab_keyboard
!= NULL
) {
864 g_object_unref (priv
->grab_keyboard
);
865 priv
->grab_keyboard
= NULL
;
868 if (priv
->grab_pointer
!= NULL
) {
872 g_object_unref (priv
->grab_pointer
);
873 priv
->grab_pointer
= NULL
;
883 gtk_date_entry_popup_key_event (GtkWidget
*widget
, GdkEventKey
*event
, gpointer user_data
)
885 GtkDateEntry
*dateentry
= user_data
;
887 DB( g_print("\n[dateentry] popup_key_event%d\n", event
->keyval
) );
889 DB( g_print(" -> key=%d\n", event
->keyval
) );
891 if (event
->keyval
!= GDK_KEY_Escape
&& event
->keyval
!= GDK_KEY_Return
)
894 g_signal_stop_emission_by_name (widget
, "key-press-event");
896 gtk_date_entry_popdown(dateentry
);
903 gtk_date_entry_popup_button_press (GtkWidget
* widget
, GdkEvent
* event
, gpointer user_data
)
905 GtkDateEntry
*dateentry
= user_data
;
906 //GtkDateEntryPrivate *priv = dateentry->priv;
909 DB( g_print("\n[dateentry] popup_button_press\n") );
911 child
= gtk_get_event_widget (event
);
913 /* We don't ask for button press events on the grab widget, so
914 * if an event is reported directly to the grab widget, it must
915 * be on a window outside the application (and thus we remove
916 * the popup window). Otherwise, we check if the widget is a child
917 * of the grab widget, and only remove the popup window if it
920 if (child
!= widget
) {
924 child
= gtk_widget_get_parent (child
);
928 gtk_date_entry_popdown(dateentry
);