Log Message
[GTK] Add picker UI for <input type=date> and <input type=datetime-local> https://bugs.webkit.org/show_bug.cgi?id=224924
Patch by Carlos Garcia Campos <[email protected]> on 2021-05-10 Reviewed by Adrian Perez de Castro. Use a GtkPopover with a GtkCalendar. * UIProcess/API/gtk/WebKitWebViewBase.cpp: (webkitWebViewBaseSetFocus): Only notify the web process about focus changes when shouldNotifyFocusEvents is true. (webkitWebViewBaseSetShouldNotifyFocusEvents): Set whether the web view should notify about focus changes to the web process. * UIProcess/API/gtk/WebKitWebViewBasePrivate.h: * UIProcess/gtk/WebDateTimePickerGtk.cpp: (WebKit::WebDateTimePickerGtk::~WebDateTimePickerGtk): Call invalidate instead of endPicker. (WebKit::WebDateTimePickerGtk::invalidate): Destroy the popover and allow the web view to notify about focus events again. (WebKit::WebDateTimePickerGtk::endPicker): Invalidate and notify the parent. (WebKit::timeToString): Helper to convert the time portions of a DateComponents to a string. (WebKit::calendarDateToString): Helper to convert selected date to a string. (WebKit::WebDateTimePickerGtk::didChooseDate): Notify the WebPageProxy about the selected date. (WebKit::WebDateTimePickerGtk::showDateTimePicker): Create or update a GtkPopover with a calendar. (WebKit::WebDateTimePickerGtk::update): Update the calendar and current date. * UIProcess/gtk/WebDateTimePickerGtk.h:
Modified Paths
Diff
Modified: trunk/Source/WebKit/ChangeLog (277261 => 277262)
--- trunk/Source/WebKit/ChangeLog 2021-05-10 10:55:30 UTC (rev 277261)
+++ trunk/Source/WebKit/ChangeLog 2021-05-10 12:17:46 UTC (rev 277262)
@@ -1,5 +1,31 @@
2021-05-10 Carlos Garcia Campos <[email protected]>
+ [GTK] Add picker UI for <input type=date> and <input type=datetime-local>
+ https://bugs.webkit.org/show_bug.cgi?id=224924
+
+ Reviewed by Adrian Perez de Castro.
+
+ Use a GtkPopover with a GtkCalendar.
+
+ * UIProcess/API/gtk/WebKitWebViewBase.cpp:
+ (webkitWebViewBaseSetFocus): Only notify the web process about focus changes when shouldNotifyFocusEvents is true.
+ (webkitWebViewBaseSetShouldNotifyFocusEvents): Set whether the web view should notify about focus changes to the
+ web process.
+ * UIProcess/API/gtk/WebKitWebViewBasePrivate.h:
+ * UIProcess/gtk/WebDateTimePickerGtk.cpp:
+ (WebKit::WebDateTimePickerGtk::~WebDateTimePickerGtk): Call invalidate instead of endPicker.
+ (WebKit::WebDateTimePickerGtk::invalidate): Destroy the popover and allow the web view to notify about focus
+ events again.
+ (WebKit::WebDateTimePickerGtk::endPicker): Invalidate and notify the parent.
+ (WebKit::timeToString): Helper to convert the time portions of a DateComponents to a string.
+ (WebKit::calendarDateToString): Helper to convert selected date to a string.
+ (WebKit::WebDateTimePickerGtk::didChooseDate): Notify the WebPageProxy about the selected date.
+ (WebKit::WebDateTimePickerGtk::showDateTimePicker): Create or update a GtkPopover with a calendar.
+ (WebKit::WebDateTimePickerGtk::update): Update the calendar and current date.
+ * UIProcess/gtk/WebDateTimePickerGtk.h:
+
+2021-05-10 Carlos Garcia Campos <[email protected]>
+
[GTK] Use always async scrolling in accelerated compositing mode
https://bugs.webkit.org/show_bug.cgi?id=225512
Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp (277261 => 277262)
--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp 2021-05-10 10:55:30 UTC (rev 277261)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBase.cpp 2021-05-10 12:17:46 UTC (rev 277262)
@@ -284,6 +284,7 @@
IntSize contentsSize;
Optional<MotionEvent> lastMotionEvent;
bool isBlank;
+ bool shouldNotifyFocusEvents { true };
GtkWindow* toplevelOnScreenWindow { nullptr };
#if USE(GTK4)
@@ -2337,6 +2338,8 @@
void webkitWebViewBaseSetFocus(WebKitWebViewBase* webViewBase, bool focused)
{
WebKitWebViewBasePrivate* priv = webViewBase->priv;
+ if (!priv->shouldNotifyFocusEvents)
+ return;
if ((focused && priv->activityState & ActivityState::IsFocused) || (!focused && !(priv->activityState & ActivityState::IsFocused)))
return;
@@ -2918,3 +2921,8 @@
priv->pageGrabbedTouch = true;
gtk_gesture_set_state(priv->touchGestureGroup, GTK_EVENT_SEQUENCE_DENIED);
}
+
+void webkitWebViewBaseSetShouldNotifyFocusEvents(WebKitWebViewBase* webViewBase, bool shouldNotifyFocusEvents)
+{
+ webViewBase->priv->shouldNotifyFocusEvents = shouldNotifyFocusEvents;
+}
Modified: trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h (277261 => 277262)
--- trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h 2021-05-10 10:55:30 UTC (rev 277261)
+++ trunk/Source/WebKit/UIProcess/API/gtk/WebKitWebViewBasePrivate.h 2021-05-10 12:17:46 UTC (rev 277262)
@@ -115,4 +115,5 @@
void webkitWebViewBaseSynthesizeCompositionKeyPress(WebKitWebViewBase*, const String& text, Optional<Vector<WebCore::CompositionUnderline>>&&, Optional<WebKit::EditingRange>&&);
void webkitWebViewBaseMakeBlank(WebKitWebViewBase*, bool);
-void webkitWebViewBasePageGrabbedTouch(WebKitWebViewBase* webkitWebViewBase);
+void webkitWebViewBasePageGrabbedTouch(WebKitWebViewBase*);
+void webkitWebViewBaseSetShouldNotifyFocusEvents(WebKitWebViewBase*, bool);
Modified: trunk/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp (277261 => 277262)
--- trunk/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp 2021-05-10 10:55:30 UTC (rev 277261)
+++ trunk/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.cpp 2021-05-10 12:17:46 UTC (rev 277262)
@@ -27,11 +27,13 @@
#include "config.h"
#include "WebDateTimePickerGtk.h"
-#include <wtf/StackTrace.h>
-#include <wtf/StringPrintStream.h>
-
#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
+#include "WebKitWebViewBasePrivate.h"
+#include <gtk/gtk.h>
+#include <wtf/SetForScope.h>
+#include <wtf/glib/GRefPtr.h>
+
namespace WebKit {
Ref<WebDateTimePickerGtk> WebDateTimePickerGtk::create(WebPageProxy& page)
@@ -41,7 +43,7 @@
WebDateTimePickerGtk::~WebDateTimePickerGtk()
{
- endPicker();
+ invalidate();
}
WebDateTimePickerGtk::WebDateTimePickerGtk(WebPageProxy& page)
@@ -49,14 +51,141 @@
{
}
+void WebDateTimePickerGtk::invalidate()
+{
+ if (!m_popover)
+ return;
+
+ g_signal_handlers_disconnect_by_data(m_popover, this);
+#if USE(GTK4)
+ auto* webView = gtk_widget_get_parent(m_popover);
+ gtk_widget_unparent(m_popover);
+#else
+ auto* webView = gtk_popover_get_relative_to(GTK_POPOVER(m_popover));
+ gtk_widget_destroy(m_popover);
+#endif
+ m_popover = nullptr;
+ m_calendar = nullptr;
+
+ webkitWebViewBaseSetShouldNotifyFocusEvents(WEBKIT_WEB_VIEW_BASE(webView), true);
+}
+
void WebDateTimePickerGtk::endPicker()
{
+ invalidate();
+ WebDateTimePicker::endPicker();
}
+static String timeToString(const WebCore::DateComponents& time, WebCore::SecondFormat secondFormat)
+{
+ switch (secondFormat) {
+ case SecondFormat::None:
+ return makeString(pad('0', 2, time.hour()), ':', pad('0', 2, time.minute()));
+ case SecondFormat::Second:
+ return makeString(pad('0', 2, time.hour()), ':', pad('0', 2, time.minute()), ':', pad('0', 2, time.second()));
+ case SecondFormat::Millisecond:
+ return makeString(pad('0', 2, time.hour()), ':', pad('0', 2, time.minute()), ':', pad('0', 2, time.second()), '.', pad('0', 3, time.millisecond()));
+ }
+
+ ASSERT_NOT_REACHED();
+ return { };
+}
+
+static String calendarDateToString(int year, int month, int day, const Optional<WebCore::DateComponents>& date, WebCore::SecondFormat secondFormat)
+{
+ auto type = date ? date->type() : WebCore::DateComponentsType::Date;
+ switch (type) {
+ case WebCore::DateComponentsType::Date:
+ return makeString(pad('0', 4, year), '-', pad('0', 2, month + 1), '-', pad('0', 2, day));
+ case WebCore::DateComponentsType::DateTimeLocal:
+ return makeString(pad('0', 4, year), '-', pad('0', 2, month + 1), '-', pad('0', 2, day), 'T', timeToString(*date, secondFormat));
+ case WebCore::DateComponentsType::Invalid:
+ case WebCore::DateComponentsType::Month:
+ case WebCore::DateComponentsType::Time:
+ case WebCore::DateComponentsType::Week:
+ break;
+ }
+
+ ASSERT_NOT_REACHED();
+ return { };
+}
+
+void WebDateTimePickerGtk::didChooseDate()
+{
+ if (m_inUpdate)
+ return;
+
+ if (!m_page)
+ return;
+
+ int year, month, day;
+ g_object_get(m_calendar, "year", &year, "month", &month, "day", &day, nullptr);
+ m_page->didChooseDate(calendarDateToString(year, month, day, m_currentDate, m_secondFormat));
+}
+
void WebDateTimePickerGtk::showDateTimePicker(WebCore::DateTimeChooserParameters&& params)
{
+ if (m_popover) {
+ update(WTFMove(params));
+ return;
+ }
+
+ auto* webView = m_page->viewWidget();
+ webkitWebViewBaseSetShouldNotifyFocusEvents(WEBKIT_WEB_VIEW_BASE(webView), false);
+
+#if USE(GTK4)
+ m_popover = gtk_popover_new();
+ gtk_popover_set_has_arrow(GTK_POPOVER(m_popover), FALSE);
+ gtk_widget_set_parent(m_popover, webView);
+#else
+ m_popover = gtk_popover_new(webView);
+#endif
+ gtk_popover_set_position(GTK_POPOVER(m_popover), GTK_POS_BOTTOM);
+ GdkRectangle rectInRootView = params.anchorRectInRootView;
+ gtk_popover_set_pointing_to(GTK_POPOVER(m_popover), &rectInRootView);
+ g_signal_connect_swapped(m_popover, "closed", G_CALLBACK(+[](WebDateTimePickerGtk* picker) {
+ picker->endPicker();
+ }), this);
+
+ m_calendar = gtk_calendar_new();
+ g_signal_connect(m_calendar, "day-selected", G_CALLBACK(+[](GtkCalendar* calendar, WebDateTimePickerGtk* picker) {
+ picker->didChooseDate();
+ }), this);
+#if USE(GTK4)
+ gtk_popover_set_child(GTK_POPOVER(m_popover), m_calendar);
+#else
+ gtk_container_add(GTK_CONTAINER(m_popover), m_calendar);
+ gtk_widget_show(m_calendar);
+#endif
+
+ update(WTFMove(params));
+
+ gtk_popover_popup(GTK_POPOVER(m_popover));
}
+void WebDateTimePickerGtk::update(WebCore::DateTimeChooserParameters&& params)
+{
+ SetForScope<bool> inUpdate(m_inUpdate, true);
+ if (params.type == "date")
+ m_currentDate = WebCore::DateComponents::fromParsingDate(params.currentValue);
+ else if (params.type == "datetime-local")
+ m_currentDate = WebCore::DateComponents::fromParsingDateTimeLocal(params.currentValue);
+
+ if (m_currentDate)
+ g_object_set(m_calendar, "year", m_currentDate->fullYear(), "month", m_currentDate->month(), "day", m_currentDate->monthDay(), nullptr);
+ else if (params.type == "datetime-local") {
+ GRefPtr<GDateTime> now = adoptGRef(g_date_time_new_now_local());
+ Seconds unixTime = Seconds(g_date_time_to_unix(now.get())) + Seconds::fromMicroseconds(g_date_time_get_utc_offset(now.get()));
+ m_currentDate = WebCore::DateComponents::fromMillisecondsSinceEpochForDateTimeLocal(unixTime.milliseconds());
+ if (params.hasMillisecondField)
+ m_secondFormat = WebCore::SecondFormat::Millisecond;
+ else if (params.hasSecondField)
+ m_secondFormat = WebCore::SecondFormat::Second;
+ else
+ m_secondFormat = WebCore::SecondFormat::None;
+ }
+}
+
} // namespace WebKit
#endif // ENABLE(DATE_AND_TIME_INPUT_TYPES)
Modified: trunk/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.h (277261 => 277262)
--- trunk/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.h 2021-05-10 10:55:30 UTC (rev 277261)
+++ trunk/Source/WebKit/UIProcess/gtk/WebDateTimePickerGtk.h 2021-05-10 12:17:46 UTC (rev 277262)
@@ -29,6 +29,7 @@
#if ENABLE(DATE_AND_TIME_INPUT_TYPES)
#include "WebDateTimePicker.h"
+#include <WebCore/DateComponents.h>
#include <WebCore/DateTimeChooserParameters.h>
namespace WebKit {
@@ -43,6 +44,16 @@
void endPicker() final;
void showDateTimePicker(WebCore::DateTimeChooserParameters&&) final;
+
+ void update(WebCore::DateTimeChooserParameters&&);
+ void didChooseDate();
+ void invalidate();
+
+ GtkWidget* m_popover { nullptr };
+ GtkWidget* m_calendar { nullptr };
+ Optional<WebCore::DateComponents> m_currentDate;
+ WebCore::SecondFormat m_secondFormat { WebCore::SecondFormat::None };
+ bool m_inUpdate { false };
};
} // namespace WebKit
_______________________________________________ webkit-changes mailing list [email protected] https://lists.webkit.org/mailman/listinfo/webkit-changes
