[Goodies-dev] [PATCH 3/4] Add calendar popup menu to go to/select today

Olivier Brunel jjk at jjacky.com
Sun May 13 21:43:06 CEST 2018


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 <jjk at jjacky.com>
---
 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.15.1



More information about the Goodies-dev mailing list