From cb190379888fdc7546a5085c2952eb79e86cc941 Mon Sep 17 00:00:00 2001 From: Olivier Brunel Date: Sun, 18 Mar 2018 14:26:17 +0100 Subject: [PATCH 3/4] Add calendar popup menu to go to/select today Also refactor calendar creation via a function. This will all become (more) useful in the next commit when adding reminders. Signed-off-by: Olivier Brunel --- panel-plugin/datetime.c | 110 +++++++++++++++++++++++++++++++++++++--- panel-plugin/datetime.h | 6 +++ 2 files changed, 109 insertions(+), 7 deletions(-) diff --git a/panel-plugin/datetime.c b/panel-plugin/datetime.c index 1722dd1..a96f791 100644 --- a/panel-plugin/datetime.c +++ b/panel-plugin/datetime.c @@ -259,6 +259,104 @@ static gboolean close_calendar_window(t_datetime *datetime) return TRUE; } +static gboolean unblock_focus_out(GtkWidget *cal) +{ + gulong bop_sid; + + bop_sid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cal), "block-on-popup-sid")); + if (G_LIKELY(bop_sid)) + { + GtkWidget *win; + + win = gtk_widget_get_toplevel(cal); + g_signal_handler_unblock(win, bop_sid); + } + + return G_SOURCE_REMOVE; +} + +static void on_today_activate(GtkCalendar *cal) +{ + time_t ts; + struct tm tm; + + ts = time(NULL); + if (!localtime_r(&ts, &tm)) + return; + + gtk_calendar_select_month(cal, tm.tm_mon, tm.tm_year + 1900); + gtk_calendar_select_day(cal, tm.tm_mday); +} + +void inline menu_popup_and_destroy(GtkMenu *menu, guint button, guint32 time) +{ + g_signal_connect_swapped(G_OBJECT(menu), "hide", + G_CALLBACK(gtk_widget_destroy), + menu); + gtk_menu_popup(menu, NULL, NULL, NULL, NULL, button, time); +} + +static gboolean on_calendar_button_released(GtkWidget *cal, + GdkEventButton *event, + t_datetime *datetime) +{ + GtkWidget *menu; + GtkWidget *w; + gulong bop_sid; + + if (event->button != GDK_BUTTON_SECONDARY) + return FALSE; + + /* check if a signal was set to block on pop-up. This is because if the + * toplevel window containing the calendar autocloses on loss of focus, it + * would autoclose because of the menu popup */ + bop_sid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cal), "block-on-popup-sid")); + if (bop_sid) + { + GtkWidget *win; + + win = gtk_widget_get_toplevel(cal); + g_signal_handler_block(win, bop_sid); + } + + menu = gtk_menu_new(); + + w = gtk_menu_item_new_with_label(_("Today")); + /* FIXME somehow with "activate" is doesn't work? (callback never triggered) */ + g_signal_connect_swapped(G_OBJECT(w), "button-release-event", + G_CALLBACK(on_today_activate), + cal); + gtk_menu_attach(GTK_MENU(menu), w, 0, 1, 0, 1); + + gtk_widget_show_all(menu); + menu_popup_and_destroy(GTK_MENU(menu), event->button, event->time); + + /* restore autoclosing once done */ + if (bop_sid) + g_idle_add((GSourceFunc) unblock_focus_out, cal); + + return TRUE; +} + +GtkWidget * datetime_calendar_new(t_datetime *datetime) +{ + GtkWidget *cal; + GtkCalendarDisplayOptions display_options; + + cal = gtk_calendar_new(); + + display_options = GTK_CALENDAR_SHOW_HEADING | + GTK_CALENDAR_SHOW_WEEK_NUMBERS | + GTK_CALENDAR_SHOW_DAY_NAMES; + gtk_calendar_set_display_options(GTK_CALENDAR(cal), display_options); + + g_signal_connect(G_OBJECT(cal), "button-release-event", + G_CALLBACK(on_calendar_button_released), + datetime); + + return cal; +} + /* * call the gtk calendar */ @@ -269,7 +367,7 @@ static GtkWidget * pop_calendar_window(t_datetime *datetime, int orientation) GtkWidget *cal; GtkWidget *parent = datetime->button; GdkScreen *screen; - GtkCalendarDisplayOptions display_options; + gulong sid; int num; window = gtk_window_new(GTK_WINDOW_TOPLEVEL); @@ -288,11 +386,7 @@ static GtkWidget * pop_calendar_window(t_datetime *datetime, int orientation) gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_OUT); gtk_container_add (GTK_CONTAINER(window), frame); - cal = gtk_calendar_new(); - display_options = GTK_CALENDAR_SHOW_HEADING | - GTK_CALENDAR_SHOW_WEEK_NUMBERS | - GTK_CALENDAR_SHOW_DAY_NAMES; - gtk_calendar_set_display_options(GTK_CALENDAR (cal), display_options); + cal = datetime_calendar_new(datetime); gtk_container_add (GTK_CONTAINER(frame), cal); g_signal_connect_after(G_OBJECT(window), "realize", @@ -301,9 +395,11 @@ static GtkWidget * pop_calendar_window(t_datetime *datetime, int orientation) g_signal_connect_swapped(G_OBJECT(window), "delete-event", G_CALLBACK(close_calendar_window), datetime); - g_signal_connect_swapped(G_OBJECT(window), "focus-out-event", + sid = g_signal_connect_swapped(G_OBJECT(window), "focus-out-event", G_CALLBACK(close_calendar_window), datetime); + /* set as signal to block on popup -- see on_calendar_button_released */ + g_object_set_data(G_OBJECT(cal), "block-on-popup-sid", GINT_TO_POINTER(sid)); gtk_widget_show_all(window); xfce_panel_plugin_block_autohide (XFCE_PANEL_PLUGIN (datetime->plugin), TRUE); diff --git a/panel-plugin/datetime.h b/panel-plugin/datetime.h index 3fe434b..109bd0a 100644 --- a/panel-plugin/datetime.h +++ b/panel-plugin/datetime.h @@ -107,5 +107,11 @@ void datetime_write_rc_file(XfcePanelPlugin *plugin, t_datetime *dt); +GtkWidget * +datetime_calendar_new(t_datetime *datetime); + +void +menu_popup_and_destroy(GtkMenu *menu, guint button, guint32 time); + #endif /* datetime.h */ -- 2.19.0