From 1c5fbc3107fa23264689e2b3dd5599e08f7cb282 Mon Sep 17 00:00:00 2001 From: Cameron Kaiser Date: Sat, 30 Jun 2018 09:24:55 -0700 Subject: [PATCH] #405: implement interface, widget, plumbing for time picker --- dom/html/HTMLInputElement.cpp | 1 + dom/ipc/PBrowser.ipdl | 4 + dom/ipc/PTimePicker.ipdl | 27 ++ dom/ipc/TabChild.cpp | 16 + dom/ipc/TabChild.h | 5 + dom/ipc/TabParent.cpp | 14 + dom/ipc/TabParent.h | 4 + dom/ipc/TimePickerParent.cpp | 93 +++++ dom/ipc/TimePickerParent.h | 63 ++++ dom/ipc/moz.build | 2 + widget/cocoa/moz.build | 1 + widget/cocoa/nsDatePicker.mm | 2 + widget/cocoa/nsTimePicker.h | 52 +++ widget/cocoa/nsTimePicker.mm | 461 +++++++++++++++++++++++ widget/cocoa/nsWidgetFactory.mm | 7 + widget/moz.build | 5 +- widget/nsBaseTimePicker.cpp | 98 +++++ widget/nsBaseTimePicker.h | 37 ++ widget/nsContentProcessWidgetFactory.cpp | 6 + widget/nsIDatePicker.idl | 4 +- widget/nsITimePicker.idl | 92 +++++ widget/nsTimePickerProxy.cpp | 89 +++++ widget/nsTimePickerProxy.h | 71 ++++ widget/nsWidgetsCID.h | 5 + 24 files changed, 1156 insertions(+), 3 deletions(-) create mode 100644 dom/ipc/PTimePicker.ipdl create mode 100644 dom/ipc/TimePickerParent.cpp create mode 100644 dom/ipc/TimePickerParent.h create mode 100644 widget/cocoa/nsTimePicker.h create mode 100644 widget/cocoa/nsTimePicker.mm create mode 100644 widget/nsBaseTimePicker.cpp create mode 100644 widget/nsBaseTimePicker.h create mode 100644 widget/nsITimePicker.idl create mode 100644 widget/nsTimePickerProxy.cpp create mode 100644 widget/nsTimePickerProxy.h diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index a83712ee0e..487153f8f4 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -113,6 +113,7 @@ #include "nsIColorPicker.h" #include "nsIDatePicker.h" // TenFourFox issue 405 +#include "nsITimePicker.h" // TenFourFox issue 405 #include "nsIStringEnumerator.h" #include "HTMLSplitOnSpacesTokenizer.h" #include "nsIController.h" diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 2d00c0a735..c490e25926 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -15,6 +15,7 @@ include protocol PDatePicker; include protocol PFilePicker; include protocol PIndexedDBPermissionRequest; include protocol PRenderFrame; +include protocol PTimePicker; include protocol PPluginWidget; include DOMTypes; include JavaScriptTypes; @@ -106,6 +107,7 @@ prio(normal upto urgent) sync protocol PBrowser manages PDocumentRenderer; manages PFilePicker; manages PDatePicker; + manages PTimePicker; manages PIndexedDBPermissionRequest; manages PRenderFrame; manages PPluginWidget; @@ -381,6 +383,8 @@ parent: PDatePicker(nsString aTitle); + PTimePicker(nsString aTitle); + /** * Initiates an asynchronous request for one of the special indexedDB * permissions for the provided principal. diff --git a/dom/ipc/PTimePicker.ipdl b/dom/ipc/PTimePicker.ipdl new file mode 100644 index 0000000000..81c9896a99 --- /dev/null +++ b/dom/ipc/PTimePicker.ipdl @@ -0,0 +1,27 @@ +/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8 -*- */ +/* vim: set sw=4 ts=8 et tw=80 ft=cpp : */ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +include protocol PBrowser; + +namespace mozilla { +namespace dom { + +protocol PTimePicker +{ + manager PBrowser; + +parent: + Open(); + +child: + Update(nsString time); + + __delete__(nsString time); +}; + +} // namespace dom +} // namespace mozilla diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 587db4df20..551ace46e7 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -54,6 +54,7 @@ #include "nsExceptionHandler.h" #endif #include "nsDatePickerProxy.h" +#include "nsTimePickerProxy.h" #include "nsFilePickerProxy.h" #include "mozilla/dom/Element.h" #include "nsIBaseWindow.h" @@ -2152,6 +2153,21 @@ TabChild::DeallocPDatePickerChild(PDatePickerChild* actor) return true; } +PTimePickerChild* +TabChild::AllocPTimePickerChild(const nsString&) +{ + NS_RUNTIMEABORT("unused"); + return nullptr; +} + +bool +TabChild::DeallocPTimePickerChild(PTimePickerChild* actor) +{ + nsTimePickerProxy* datePicker = static_cast(actor); + NS_RELEASE(datePicker); + return true; +} + auto TabChild::AllocPIndexedDBPermissionRequestChild(const Principal& aPrincipal) -> PIndexedDBPermissionRequestChild* diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 7a01e901df..cf510cc0ca 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -425,6 +425,11 @@ class TabChild final : public TabChildBase, virtual bool DeallocPDatePickerChild(PDatePickerChild* actor) override; + virtual PTimePickerChild* + AllocPTimePickerChild(const nsString& aTitle) override; + virtual bool + DeallocPTimePickerChild(PTimePickerChild* actor) override; + virtual PIndexedDBPermissionRequestChild* AllocPIndexedDBPermissionRequestChild(const Principal& aPrincipal) override; diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index b855b0f81d..6e45f19caa 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -79,6 +79,7 @@ #include "StructuredCloneData.h" #include "ColorPickerParent.h" #include "DatePickerParent.h" +#include "TimePickerParent.h" #include "FilePickerParent.h" #include "TabChild.h" #include "LoadContext.h" @@ -1228,6 +1229,19 @@ TabParent::DeallocPDatePickerParent(PDatePickerParent* actor) return true; } +PTimePickerParent* +TabParent::AllocPTimePickerParent(const nsString& aTitle) +{ + return new TimePickerParent(aTitle); +} + +bool +TabParent::DeallocPTimePickerParent(PTimePickerParent* actor) +{ + delete actor; + return true; +} + auto TabParent::AllocPIndexedDBPermissionRequestParent(const Principal& aPrincipal) -> PIndexedDBPermissionRequestParent* diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index 0e78c97bf6..ca0e56cf19 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -368,6 +368,10 @@ class TabParent final : public PBrowserParent AllocPDatePickerParent(const nsString& aTitle) override; virtual bool DeallocPDatePickerParent(PDatePickerParent* actor) override; + virtual PTimePickerParent* + AllocPTimePickerParent(const nsString& aTitle) override; + virtual bool DeallocPTimePickerParent(PTimePickerParent* actor) override; + virtual PIndexedDBPermissionRequestParent* AllocPIndexedDBPermissionRequestParent(const Principal& aPrincipal) override; diff --git a/dom/ipc/TimePickerParent.cpp b/dom/ipc/TimePickerParent.cpp new file mode 100644 index 0000000000..3ea2191615 --- /dev/null +++ b/dom/ipc/TimePickerParent.cpp @@ -0,0 +1,93 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "TimePickerParent.h" +#include "nsComponentManagerUtils.h" +#include "nsIDocument.h" +#include "nsIDOMWindow.h" +#include "mozilla/unused.h" +#include "mozilla/dom/Element.h" +#include "mozilla/dom/TabParent.h" + +using mozilla::Unused; +using namespace mozilla::dom; + +NS_IMPL_ISUPPORTS(TimePickerParent::TimePickerShownCallback, + nsITimePickerShownCallback); + +NS_IMETHODIMP +TimePickerParent::TimePickerShownCallback::Update(const nsAString& aTime) +{ + if (mTimePickerParent) { + Unused << mTimePickerParent->SendUpdate(nsString(aTime)); + } + return NS_OK; +} + +NS_IMETHODIMP +TimePickerParent::TimePickerShownCallback::Done(int16_t aResult) +{ + if (mTimePickerParent) { + mTimePickerParent->Done(aResult); + } + return NS_OK; +} + +void +TimePickerParent::TimePickerShownCallback::Destroy() +{ + mTimePickerParent = nullptr; +} + +bool +TimePickerParent::CreateTimePicker() +{ + mPicker = do_CreateInstance("@mozilla.org/timepicker;1"); + if (!mPicker) { + return false; + } + + Element* ownerElement = TabParent::GetFrom(Manager())->GetOwnerElement(); + if (!ownerElement) { + return false; + } + + nsCOMPtr window = do_QueryInterface(ownerElement->OwnerDoc()->GetWindow()); + if (!window) { + return false; + } + + return NS_SUCCEEDED(mPicker->Init(window, mTitle)); +} + +void +TimePickerParent::Done(int16_t aResult) +{ + Unused << Send__delete__(this, nsString()); + MOZ_CRASH("TimePickerParent::Done NYI"); +} + +bool +TimePickerParent::RecvOpen() +{ + if (!CreateTimePicker()) { + Unused << Send__delete__(this, nsString()); + return true; + } + + mCallback = new TimePickerShownCallback(this); + + mPicker->Open(mCallback); + return true; +}; + +void +TimePickerParent::ActorDestroy(ActorDestroyReason aWhy) +{ + if (mCallback) { + mCallback->Destroy(); + } +} diff --git a/dom/ipc/TimePickerParent.h b/dom/ipc/TimePickerParent.h new file mode 100644 index 0000000000..2e4a52b15d --- /dev/null +++ b/dom/ipc/TimePickerParent.h @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_TimePickerParent_h +#define mozilla_dom_TimePickerParent_h + +#include "mozilla/dom/PTimePickerParent.h" +#include "nsITimePicker.h" + +namespace mozilla { +namespace dom { + +class TimePickerParent : public PTimePickerParent +{ + public: + TimePickerParent(const nsString& aTitle) + : mTitle(aTitle) + {} + + virtual bool RecvOpen() override; + virtual void ActorDestroy(ActorDestroyReason aWhy) override; + + void Done(int16_t aResult); + + class TimePickerShownCallback final + : public nsITimePickerShownCallback + { + public: + explicit TimePickerShownCallback(TimePickerParent* aTimePickerParent) + : mTimePickerParent(aTimePickerParent) + {} + + NS_DECL_ISUPPORTS + NS_DECL_NSIDATEPICKERSHOWNCALLBACK + + NS_IMETHODIMP Update(const nsAString& aTime); + + void Destroy(); + + private: + ~TimePickerShownCallback() {} + + TimePickerParent* mTimePickerParent; + }; + + private: + virtual ~TimePickerParent() {} + + bool CreateTimePicker(); + + RefPtr mCallback; + nsCOMPtr mPicker; + + nsString mTitle; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_TimePickerParent_h diff --git a/dom/ipc/moz.build b/dom/ipc/moz.build index a091b2cf53..816b28dae0 100644 --- a/dom/ipc/moz.build +++ b/dom/ipc/moz.build @@ -76,6 +76,7 @@ UNIFIED_SOURCES += [ 'TabContext.cpp', 'TabMessageUtils.cpp', 'TabParent.cpp', + 'TimePickerParent.cpp', ] # Blob.cpp cannot be compiled in unified mode because it triggers a fatal gcc warning. @@ -112,6 +113,7 @@ IPDL_SOURCES += [ 'PProcessHangMonitor.ipdl', 'PScreenManager.ipdl', 'PTabContext.ipdlh', + 'PTimePicker.ipdl', ] include('/ipc/chromium/chromium-config.mozbuild') diff --git a/widget/cocoa/moz.build b/widget/cocoa/moz.build index 3860e20383..6d68d25427 100644 --- a/widget/cocoa/moz.build +++ b/widget/cocoa/moz.build @@ -69,6 +69,7 @@ SOURCES += [ 'nsDatePicker.mm', 'nsDragService.mm', 'nsNativeThemeCocoa.mm', + 'nsTimePicker.mm', ] if not CONFIG['RELEASE_BUILD'] or CONFIG['MOZ_DEBUG']: diff --git a/widget/cocoa/nsDatePicker.mm b/widget/cocoa/nsDatePicker.mm index 684f27e6cc..6e72676078 100644 --- a/widget/cocoa/nsDatePicker.mm +++ b/widget/cocoa/nsDatePicker.mm @@ -80,6 +80,8 @@ - (NSDoubleDatePicker *)datePicker:(NSString *)message - (void)onSwitchControl:(NSDatePicker *)which newDate:(NSDate **)newDate; - (NSDate *)date; - (void)setDate:(NSDate *)date; +- (void)setMinDate:(NSDate *)date; +- (void)setMaxDate:(NSDate *)date; @end @interface NSDoubleDatePicker(Private) diff --git a/widget/cocoa/nsTimePicker.h b/widget/cocoa/nsTimePicker.h new file mode 100644 index 0000000000..ce2e970604 --- /dev/null +++ b/widget/cocoa/nsTimePicker.h @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsTimePicker_h_ +#define nsTimePicker_h_ + +#include "nsBaseTimePicker.h" + +class nsTimePicker : public nsBaseTimePicker +{ +public: + nsTimePicker(); + + NS_DECL_ISUPPORTS + + // nsITimePicker (less what's in nsBaseTimePicker) + NS_IMETHOD Show(int16_t *_retval) override; + NS_IMETHOD GetDefaultTime(nsAString &aDefaultTime) override; + NS_IMETHOD SetDefaultTime(const nsAString &aDefaultTime) override; + NS_IMETHOD GetMinTime(nsAString &aMinTime) override; + NS_IMETHOD SetMinTime(const nsAString &aMinTime) override; + NS_IMETHOD GetMaxTime(nsAString &aMaxTime) override; + NS_IMETHOD SetMaxTime(const nsAString &aMaxTime) override; + NS_IMETHOD GetStep(double *aStep) override; + NS_IMETHOD SetStep(const double aStep) override; + NS_IMETHOD GetSelectedTime(nsAString &aSelectedTime); + +protected: + virtual ~nsTimePicker(); + + virtual void InitNative(nsIWidget *aParent, const nsAString& aTitle) override; + + int16_t GetTime(); + + // Native control controls + void SetDialogTitle(const nsString& inTitle, id aDialog); + + nsString mTitle; + nsString mTime; + bool mHasDefault; + nsString mDefault; + nsString mMinTime; + bool mHasMin; + nsString mMaxTime; + bool mHasMax; + double mStep; +}; + +#endif // nsTimePicker_h_ diff --git a/widget/cocoa/nsTimePicker.mm b/widget/cocoa/nsTimePicker.mm new file mode 100644 index 0000000000..ada2618a5a --- /dev/null +++ b/widget/cocoa/nsTimePicker.mm @@ -0,0 +1,461 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Time Picker widget for TenFourFox (C)2018 Cameron Kaiser */ + +/* IMPORTANT! + Because the step determines how the NSDatePickers are configured and + the time format (HH:mm or HH:mm:ss), it must be set *before* setting + the default time and time range, if any. */ + +#import + +#include "nsTimePicker.h" +#include "nsCOMPtr.h" +#include "nsReadableUtils.h" +#include "nsNetUtil.h" +#include "nsIComponentManager.h" +#include "nsQueryObject.h" +#include "nsServiceManagerUtils.h" +#include "nsIStringBundle.h" +#include "nsCocoaFeatures.h" +#include "nsCocoaUtils.h" +#include "mozilla/Preferences.h" + +// This must be included last: +#include "nsObjCExceptions.h" + +// 10.4 does not have an accessory view method for NSAlert, but we can +// simulate it with these undocumented methods. +@interface NSAlert(WithCustomStyle) +- (void)prepare; +- (id)buildAlertStyle:(int)fp8 title:(id)fp12 formattedMsg:(id)fp16 first:(id)fp20 second:(id)fp24 third:(id)fp28 oldStyle:(BOOL)fp32; +- (id)buildAlertStyle:(int)fp8 title:(id)fp12 message:(id)fp16 first:(id)fp20 second:(id)fp24 third:(id)fp28 oldStyle:(BOOL)fp32 args:(char *)fp36; +@end + +@class NSDoubleTimePicker; // forward declaration + +@interface NSDoubleTimeDelegate : NSObject { + NSDoubleTimePicker *_parentAlert; + NSDatePicker *_source; +} + +- (void)datePickerCell:(NSDatePickerCell *)aDatePickerCell + validateProposedDateValue:(NSDate **)proposedDateValue + timeInterval:(NSTimeInterval *)proposedTimeInterval; +- (void)setParentAlert:(NSDoubleTimePicker *)parentAlert + withSource:(NSDatePicker *)source; +@end + +@implementation NSDoubleTimeDelegate +- (void)datePickerCell:(NSDatePickerCell *)aDatePickerCell + validateProposedDateValue:(NSDate **)proposedDateValue + timeInterval:(NSTimeInterval *)proposedTimeInterval +{ + //NSLog(@"validate"); + [_parentAlert onSwitchControl:_source newDate:proposedDateValue]; +} + +- (void)setParentAlert:(NSDoubleTimePicker *)parentAlert + withSource:(NSDatePicker *)source +{ + _parentAlert = parentAlert; + _source = source; +} +@end + +////// NSDoubleTimePicker +////// based on NSAlertCheckbox, http://cocoadev.github.io/NSAlertCheckbox/ + +@interface NSDoubleTimePicker : NSAlert { + NSDatePicker *_pickertop; + NSDatePicker *_pickerbottom; + NSDoubleTimeDelegate *_topdelegate; + NSDoubleTimeDelegate *_bottomdelegate; + double step; +} + +- (void)dealloc; +- (NSDoubleTimePicker *)datePicker:(NSString *)message + defaultButton:(NSString *)defaultButton + alternateButton:(NSString *)alternateButton + otherButton:(NSString *)otherButton + informativeTextWithFormat:(NSString *)format; +- (void)onSwitchControl:(NSDatePicker *)which newDate:(NSDate **)newDate; +- (void)setStep:(double)newStep; +- (NSDate *)time; +- (void)setTime:(NSDate *)time; +- (void)setMinTime:(NSDate *)time; +- (void)setMaxTime:(NSDate *)time; +@end + +@interface NSDoubleTimePicker(Private) +- (void)_ensureDatePickers; +- (void)_addDatePickersToAlert; +@end + +@implementation NSDoubleTimePicker + +- (void)dealloc +{ +//NSLog(@"dealloc"); + [_pickertop release]; + [_pickerbottom release]; + [_topdelegate release]; + [_bottomdelegate release]; + [super dealloc]; +} + +- (NSDoubleTimePicker *)datePicker:(NSString *)message + defaultButton:(NSString *)defaultButton + alternateButton:(NSString *)alternateButton + otherButton:(NSString *)otherButton + informativeTextWithFormat:(NSString *)format +{ + NSAlert *alert = [super alertWithMessageText:message + defaultButton:defaultButton + alternateButton:alternateButton + otherButton:otherButton + informativeTextWithFormat:format]; + return (NSDoubleTimePicker *)alert; +} + +- (id)buildAlertStyle:(int)fp8 + title:(id)fp12 + formattedMsg:(id)fp16 + first:(id)fp20 + second:(id)fp24 + third:(id)fp28 + oldStyle:(BOOL)fp32 +{ + id rv = [super buildAlertStyle:fp8 + title:fp12 + formattedMsg:fp16 + first:fp20 + second:fp24 + third:fp28 + oldStyle:fp32]; + [self _addDatePickersToAlert]; + return rv; +} + +- (id)buildAlertStyle:(int)fp8 + title:(id)fp12 + message:(id)fp16 + first:(id)fp20 + second:(id)fp24 + third:(id)fp28 + oldStyle:(BOOL)fp32 + args:(char *)fp36 +{ + id rv = [super buildAlertStyle:fp8 + title:fp12 + message:fp16 + first:fp20 + second:fp24 + third:fp28 + oldStyle:fp32 + args:fp36]; + [self _addDatePickersToAlert]; + return rv; +} + +- (void)onSwitchControl:(NSDatePicker *)which newDate:(NSDate **)newDate +{ + // Halt the delegate on the one we're setting first. + if (which == _pickertop) { + //NSLog(@"control event: top"); + [_pickerbottom setDelegate:nil]; + [_pickerbottom setDateValue:*newDate]; + [_pickerbottom setDelegate:_bottomdelegate]; + } else if (which == _pickerbottom) { + //NSLog(@"control event: bottom"); + [_pickertop setDelegate:nil]; + [_pickertop setDateValue:*newDate]; + [_pickertop setDelegate:_topdelegate]; + } else + NSLog(@"wtf"); +} + +- (void)setStep:(double)newStep +{ + step = newStep; +} + +- (NSDate *)time +{ + [self _ensureDatePickers]; + return [_pickertop dateValue]; +} + +- (void)setTime:(NSDate *)time +{ + [self _ensureDatePickers]; + [_pickertop setDateValue:time]; + [_pickerbottom setDateValue:time]; +} + +- (void)setMinTime:(NSDate *)time +{ + [self _ensureDatePickers]; + [_pickertop setMinDate:time]; + [_pickerbottom setMinDate:time]; +} + +- (void)setMaxTime:(NSDate *)time +{ + [self _ensureDatePickers]; + [_pickertop setMaxDate:time]; + [_pickerbottom setMaxDate:time]; +} +@end + +@implementation NSDoubleTimePicker(Private) +- (void)_ensureDatePickers +{ + if (!_pickertop) { +// NSLog(@"picker init"); + _pickertop = [[NSDatePicker alloc] initWithFrame:NSMakeRect(10,10,295,154)]; + [_pickertop setDatePickerStyle:NSClockAndCalendarDatePickerStyle]; + if (step >= 60.0) + [_pickertop setDatePickerElements:NSHourMinuteDatePickerElementFlag]; + else + [_pickertop setDatePickerElements:NSHourMinuteSecondDatePickerElementFlag]; + + _topdelegate = [[NSDoubleTimeDelegate alloc] init]; + [_topdelegate setParentAlert:self withSource:_pickertop]; + [_pickertop setDelegate:_topdelegate]; + + _pickerbottom = [[NSDatePicker alloc] initWithFrame:NSMakeRect(10,10,295,154)]; + [_pickerbottom setDatePickerStyle:NSTextFieldAndStepperDatePickerStyle]; + if (step >= 60.0) + [_pickerbottom setDatePickerElements:NSHourMinuteDatePickerElementFlag]; + else + [_pickerbottom setDatePickerElements:NSHourMinuteSecondDatePickerElementFlag]; + + _bottomdelegate = [[NSDoubleTimeDelegate alloc] init]; + [_bottomdelegate setParentAlert:self withSource:_pickerbottom]; + [_pickerbottom setDelegate:_bottomdelegate]; + } +} + +- (void)_addDatePickersToAlert +{ + NSWindow *window = [self window]; + NSView *content = [window contentView]; + float padding = 14.0f; + + NSArray *subviews = [content subviews]; + NSEnumerator *en = [subviews objectEnumerator]; + NSView *subview = nil; + NSTextField *messageText = nil; + int count = 0; + + [self _ensureDatePickers]; + + // Find the main text field. + while (subview = [en nextObject]) { + if ([subview isKindOfClass:[NSTextField class]]) { + if (++count == 2) + messageText = (NSTextField *)subview; + } + } + if (messageText) { + [content addSubview:_pickertop]; + [_pickertop sizeToFit]; + [content addSubview:_pickerbottom]; + [_pickerbottom sizeToFit]; + + // Expand the alert window. + NSRect windowFrame = [window frame]; + NSRect topPickerFrame = [_pickertop frame]; + NSRect bottomPickerFrame = [_pickerbottom frame]; + + windowFrame.size.height += topPickerFrame.size.height + padding + + bottomPickerFrame.size.height + padding; + [window setFrame:windowFrame display:YES]; + + // Insert the pickers below the main text field. + topPickerFrame.origin.y = [messageText frame].origin.y - + bottomPickerFrame.size.height - padding - + topPickerFrame.size.height - padding; + topPickerFrame.origin.x = [messageText frame].origin.x; + + bottomPickerFrame.origin.y = topPickerFrame.origin.y + + topPickerFrame.size.height + padding; + bottomPickerFrame.origin.x = topPickerFrame.origin.x; + + [_pickertop setFrame:topPickerFrame]; + [_pickerbottom setFrame:bottomPickerFrame]; + //NSLog(@"Picker installed"); + } else + NSLog(@"Couldn't find message text, did not add pickers"); +} +@end + +using namespace mozilla; + +NS_IMPL_ISUPPORTS(nsTimePicker, nsITimePicker) + +nsTimePicker::nsTimePicker() +{ + mHasDefault = false; + mHasMin = false; + mHasMax = false; + mStep = 60.0; +} + +nsTimePicker::~nsTimePicker() +{ +} + +// XXX Not used +void +nsTimePicker::InitNative(nsIWidget *aParent, const nsAString& aTitle) +{ + mTitle = aTitle; +} + +// Display the date dialog +NS_IMETHODIMP nsTimePicker::Show(int16_t *retval) +{ + NS_ENSURE_ARG_POINTER(retval); + + *retval = returnCancel; + + int16_t userClicksOK = GetTime(); + + *retval = userClicksOK; + return NS_OK; +} + +// Returns |returnOK| if the user presses OK in the dialog. +int16_t +nsTimePicker::GetTime() +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; + nsCOMPtr stringBundle; + NSString *cancelString = @"Cancel"; + nsXPIDLString intlString; + nsresult rv; + + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setFormatterBehavior:NSDateFormatterBehavior10_4]; + if (mStep >= 60.0) + [formatter setDateFormat:@"HH:mm"]; + else + [formatter setDateFormat:@"HH:mm:ss"]; + + nsCOMPtr bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID); + rv = bundleSvc->CreateBundle("chrome://global/locale/commonDialogs.properties", getter_AddRefs(stringBundle)); + if (NS_SUCCEEDED(rv)) { + stringBundle->GetStringFromName(MOZ_UTF16("Cancel"), getter_Copies(intlString)); + if (intlString) + cancelString = [NSString stringWithCharacters:reinterpret_cast(intlString.get()) + length:intlString.Length()]; + } + + NSDoubleTimePicker *alert = [NSDoubleTimePicker + alertWithMessageText:@" "// XXX: localize this eventually + defaultButton:nil // "OK" + alternateButton:cancelString // "Cancel" + otherButton:nil // nothin' + informativeTextWithFormat:@""]; + [alert setStep:mStep]; + if (mHasDefault) { + NSDate *newTime = [formatter dateFromString:nsCocoaUtils::ToNSString(mDefault)]; + if (newTime) + [alert setTime:newTime]; + } else + [alert setTime:[NSDate date]]; + if (mHasMin) { + NSDate *newTime = [formatter dateFromString:nsCocoaUtils::ToNSString(mMinTime)]; + if (newTime) + [alert setMinTime:newTime]; + } + if (mHasMax) { + NSDate *newTime = [formatter dateFromString:nsCocoaUtils::ToNSString(mMaxTime)]; + if (newTime) + [alert setMaxTime:newTime]; + } + + nsCocoaUtils::PrepareForNativeAppModalDialog(); + int result = [alert runModal]; + nsCocoaUtils::CleanUpAfterNativeAppModalDialog(); + if (result == NSAlertAlternateReturn) // cancel + return returnCancel; + + nsCocoaUtils::GetStringForNSString([formatter stringFromDate:[alert date]], + mTime); + + return returnOK; + NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(returnCancel); +} + +// XXX Not used currently, needs localization +// Sets the dialog title to whatever it should be. If it fails, eh, +// the OS will provide a sensible default. +void +nsTimePicker::SetDialogTitle(const nsString& inTitle, id aPanel) +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + + [aPanel setTitle:[NSString stringWithCharacters:(const unichar*)inTitle.get() length:inTitle.Length()]]; + + NS_OBJC_END_TRY_ABORT_BLOCK; +} + +NS_IMETHODIMP nsTimePicker::SetDefaultTime(const nsAString& aString) +{ + mDefault = aString; + mHasDefault = true; + return NS_OK; +} + +NS_IMETHODIMP nsTimePicker::GetDefaultTime(nsAString& aString) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP nsTimePicker::SetMinTime(const nsAString& aString) +{ + mHasMin = true; + mMinTime = aString; + return NS_OK; +} + +NS_IMETHODIMP nsTimePicker::GetMinTime(nsAString& aString) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP nsTimePicker::SetMaxTime(const nsAString& aString) +{ + mHasMax = true; + mMaxTime = aString; + return NS_OK; +} + +NS_IMETHODIMP nsTimePicker::GetMaxTime(nsAString& aString) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP nsTimePicker::SetStep(const double aStep) +{ + mStep = aStep; + return NS_OK; +} + +NS_IMETHODIMP nsTimePicker::GetStep(double *aStep) +{ + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP nsTimePicker::GetSelectedTime(nsAString& aString) +{ + aString = mTime; + return NS_OK; +} diff --git a/widget/cocoa/nsWidgetFactory.mm b/widget/cocoa/nsWidgetFactory.mm index dbca7a54d9..41f1e1b2cb 100644 --- a/widget/cocoa/nsWidgetFactory.mm +++ b/widget/cocoa/nsWidgetFactory.mm @@ -16,6 +16,7 @@ #include "nsAppShell.h" #include "nsAppShellSingleton.h" #include "nsDatePicker.h" +#include "nsTimePicker.h" #include "nsFilePicker.h" #include "nsColorPicker.h" @@ -46,6 +47,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsCocoaWindow) NS_GENERIC_FACTORY_CONSTRUCTOR(nsChildView) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDatePicker) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimePicker) NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker) NS_GENERIC_FACTORY_CONSTRUCTOR(nsColorPicker) NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound) @@ -95,6 +97,7 @@ NS_DEFINE_NAMED_CID(NS_POPUP_CID); NS_DEFINE_NAMED_CID(NS_CHILD_CID); NS_DEFINE_NAMED_CID(NS_DATEPICKER_CID); +NS_DEFINE_NAMED_CID(NS_TIMEPICKER_CID); NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID); NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID); NS_DEFINE_NAMED_CID(NS_APPSHELL_CID); @@ -126,6 +129,8 @@ { &kNS_CHILD_CID, false, NULL, nsChildViewConstructor }, { &kNS_DATEPICKER_CID, false, NULL, nsDatePickerConstructor, mozilla::Module::MAIN_PROCESS_ONLY }, + { &kNS_TIMEPICKER_CID, false, NULL, nsTimePickerConstructor, + mozilla::Module::MAIN_PROCESS_ONLY }, { &kNS_FILEPICKER_CID, false, NULL, nsFilePickerConstructor, mozilla::Module::MAIN_PROCESS_ONLY }, { &kNS_COLORPICKER_CID, false, NULL, nsColorPickerConstructor, @@ -166,6 +171,8 @@ { "@mozilla.org/widgets/childwindow/mac;1", &kNS_CHILD_CID }, { "@mozilla.org/datepicker;1", &kNS_DATEPICKER_CID, mozilla::Module::MAIN_PROCESS_ONLY }, + { "@mozilla.org/timepicker;1", &kNS_TIMEPICKER_CID, + mozilla::Module::MAIN_PROCESS_ONLY }, { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, mozilla::Module::MAIN_PROCESS_ONLY }, { "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, diff --git a/widget/moz.build b/widget/moz.build index 446be92049..87106dd1a3 100644 --- a/widget/moz.build +++ b/widget/moz.build @@ -83,6 +83,7 @@ XPIDL_SOURCES += [ 'nsIScreen.idl', 'nsIScreenManager.idl', 'nsISound.idl', + 'nsITimePicker.idl', 'nsITransferable.idl', ] @@ -198,12 +199,14 @@ if CONFIG['MOZ_X11']: 'GfxInfoX11.cpp' ] -# Do not put nsDatePickerProxy.cpp into the unified sources, or we get weird +# Do not put nsDatePickerProxy.cpp etc. into unified sources, or we get weird # build problems due to an inexplicable dependency in nsPrimitiveHelpers.cpp. if toolkit == 'cocoa': SOURCES += [ 'nsBaseDatePicker.cpp', + 'nsBaseTimePicker.cpp', 'nsDatePickerProxy.cpp', + 'nsTimePickerProxy.cpp', ] if toolkit in ('cocoa', 'windows'): diff --git a/widget/nsBaseTimePicker.cpp b/widget/nsBaseTimePicker.cpp new file mode 100644 index 0000000000..1086058df4 --- /dev/null +++ b/widget/nsBaseTimePicker.cpp @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsCOMPtr.h" +#include "nsPIDOMWindow.h" +#include "nsIDocShell.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIBaseWindow.h" +#include "nsIWidget.h" + +#include "nsXPIDLString.h" +#include "nsIServiceManager.h" +#include "nsCOMArray.h" +#include "nsEnumeratorUtils.h" +#include "mozilla/Services.h" +#include "WidgetUtils.h" +#include "nsThreadUtils.h" + +#include "nsBaseTimePicker.h" + +using namespace mozilla::widget; +using namespace mozilla::dom; + +/** + * A runnable to dispatch from the main thread to the main thread to display + * the time picker while letting the showAsync method return right away. +*/ +class AsyncShowTimePicker : public nsRunnable +{ +public: + AsyncShowTimePicker(nsITimePicker *aTimePicker, + nsITimePickerShownCallback *aCallback) : + mTimePicker(aTimePicker), + mCallback(aCallback) + { + } + + NS_IMETHOD Run() + { + NS_ASSERTION(NS_IsMainThread(), + "AsyncShowTimePicker should be on the main thread!"); + + // It's possible that some widget implementations require GUI operations + // to be on the main thread, so that's why we're not dispatching to another + // thread and calling back to the main after it's done. + int16_t result = nsITimePicker::returnCancel; + nsresult rv = mTimePicker->Show(&result); + if (NS_FAILED(rv)) { + NS_ERROR("TimePicker's Show() implementation failed!"); + } + + if (mCallback) { + mCallback->Done(result); + } + return NS_OK; + } + +private: + RefPtr mTimePicker; + RefPtr mCallback; +}; + +nsBaseTimePicker::nsBaseTimePicker() +{ +} + +nsBaseTimePicker::~nsBaseTimePicker() +{ +} + +NS_IMETHODIMP nsBaseTimePicker::Init(nsIDOMWindow *aParent, + const nsAString& aTitle) +{ + NS_PRECONDITION(aParent, "Null parent passed to timepicker, no time " + "picker for you!"); + nsCOMPtr widget = WidgetUtils::DOMWindowToWidget(aParent); + NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE); + + mParent = do_QueryInterface(aParent); + if (!mParent->IsInnerWindow()) { + mParent = mParent->GetCurrentInnerWindow(); + } + + InitNative(widget, aTitle); + + return NS_OK; +} + +NS_IMETHODIMP +nsBaseTimePicker::Open(nsITimePickerShownCallback *aCallback) +{ + nsCOMPtr filePickerEvent = + new AsyncShowTimePicker(this, aCallback); + return NS_DispatchToMainThread(filePickerEvent); +} \ No newline at end of file diff --git a/widget/nsBaseTimePicker.h b/widget/nsBaseTimePicker.h new file mode 100644 index 0000000000..879684b2a3 --- /dev/null +++ b/widget/nsBaseTimePicker.h @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef nsBaseTimePicker_h__ +#define nsBaseTimePicker_h__ + +#include "nsISupports.h" +#include "nsITimePicker.h" +#include "nsCOMPtr.h" +#include "nsString.h" +#include "nsIWidget.h" + +class nsPIDOMWindow; +class nsIWidget; + +class nsBaseTimePicker : public nsITimePicker +{ +public: + nsBaseTimePicker(); + virtual ~nsBaseTimePicker(); + + NS_IMETHOD Init(nsIDOMWindow *aParent, + const nsAString& aTitle); + + NS_IMETHOD Open(nsITimePickerShownCallback *aCallback); + +protected: + virtual void InitNative(nsIWidget *aParent, const nsAString& aTitle) = 0; + + // This is an innerWindow. + nsCOMPtr mParent; +}; + +#endif // nsBaseTimePicker_h__ diff --git a/widget/nsContentProcessWidgetFactory.cpp b/widget/nsContentProcessWidgetFactory.cpp index e51c0ddbd5..2559a46daf 100644 --- a/widget/nsContentProcessWidgetFactory.cpp +++ b/widget/nsContentProcessWidgetFactory.cpp @@ -13,6 +13,7 @@ #include "nsDragServiceProxy.h" #include "nsFilePickerProxy.h" #include "nsScreenManagerProxy.h" +#include "nsTimePickerProxy.h" #include "mozilla/widget/PuppetBidiKeyboard.h" using namespace mozilla; @@ -26,6 +27,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsDatePickerProxy) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragServiceProxy) NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePickerProxy) NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerProxy) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsTimePickerProxy) NS_GENERIC_FACTORY_CONSTRUCTOR(PuppetBidiKeyboard) NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID); @@ -35,6 +37,7 @@ NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID); NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID); NS_DEFINE_NAMED_CID(PUPPETBIDIKEYBOARD_CID); NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID); +NS_DEFINE_NAMED_CID(NS_TIMEPICKER_CID); static const mozilla::Module::CIDEntry kWidgetCIDs[] = { { &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardProxyConstructor, @@ -49,6 +52,8 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = { Module::CONTENT_PROCESS_ONLY }, { &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerProxyConstructor, Module::CONTENT_PROCESS_ONLY }, + { &kNS_TIMEPICKER_CID, false, nullptr, nsTimePickerProxyConstructor, + Module::CONTENT_PROCESS_ONLY }, { &kPUPPETBIDIKEYBOARD_CID, false, NULL, PuppetBidiKeyboardConstructor, mozilla::Module::CONTENT_PROCESS_ONLY }, { nullptr } @@ -59,6 +64,7 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = { { "@mozilla.org/colorpicker;1", &kNS_COLORPICKER_CID, Module::CONTENT_PROCESS_ONLY }, { "@mozilla.org/datepicker;1", &kNS_DATEPICKER_CID, Module::CONTENT_PROCESS_ONLY }, { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID, Module::CONTENT_PROCESS_ONLY }, + { "@mozilla.org/timepicker;1", &kNS_TIMEPICKER_CID, Module::CONTENT_PROCESS_ONLY }, { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID, Module::CONTENT_PROCESS_ONLY }, { "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID, Module::CONTENT_PROCESS_ONLY }, { nullptr } diff --git a/widget/nsIDatePicker.idl b/widget/nsIDatePicker.idl index e0dfa0f249..3ba7c4008e 100644 --- a/widget/nsIDatePicker.idl +++ b/widget/nsIDatePicker.idl @@ -74,8 +74,8 @@ interface nsIDatePicker : nsISupports [deprecated] short show(); /** - * Opens the date dialog asynchrounously. - * The passed in object's done method will be called upon completion. + * Opens the date dialog asynchronously. + * The passed-in object's done method will be called upon completion. */ void open(in nsIDatePickerShownCallback aDatePickerShownCallback); }; diff --git a/widget/nsITimePicker.idl b/widget/nsITimePicker.idl new file mode 100644 index 0000000000..f131fe3198 --- /dev/null +++ b/widget/nsITimePicker.idl @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +interface nsIURI; +interface nsIDOMWindow; + +[scriptable, function, uuid(0d79adad-b244-49A5-9997-2a8cad93fc46)] +interface nsITimePickerShownCallback : nsISupports +{ + /** + * Callback which is called when a timepicker is shown and a result + * is returned. + * + * @param aResult One of returnOK, returnCancel + */ + void done(in short aResult); +}; + +[scriptable, uuid(9840d564-42c8-4d78-9a4d-71002343c920)] +interface nsITimePicker : nsISupports +{ + const short returnOK = 0; // User hit Ok, process selection + const short returnCancel = 1; // User hit cancel, ignore selection + + /** + * Initialize the time picker widget. The time picker is not valid until this + * method is called. + * + * @param title The title for the file widget + */ + void init(in nsIDOMWindow parent, in AString title); + + /** + * The time that should be suggested to the user as a default. + * The time is a string in HH:MM:SS or HH:MM format, depending on step. + * + * @throws NS_ERROR_FAILURE on attempts to get + */ + attribute AString defaultTime; + + /** + * The minimum time range. If null, there is no minimum time. + * The time is a string in HH:MM:SS or HH:MM format, depending on step. + * + * @throws NS_ERROR_FAILURE on attempts to get + */ + attribute AString minTime; + + /** + * The maximum time range. If null, there is no maximum time. + * The time is a string in HH:MM:SS or HH:MM format, depending on step. + * + * @throws NS_ERROR_FAILURE on attempts to get + */ + attribute AString maxTime; + + /** + * The step in seconds. + * If the step is less than 60 seconds, then HH:MM:SS is used, otherwise + * HH:MM. The step may be fractional. + * + * @throws NS_ERROR_FAILURE on attempts to get + * + * @plays sweet dubstep groove wubwubwubwubwubwub + */ + attribute double step; + + /** + * The selected time. + * + * @return Returns the time currently selected. + */ + readonly attribute AString selectedTime; + + /** + * Show time dialog. The dialog is displayed modally. + * + * @return returnOK if the user selects OK, returnCancel if the user selects cancel + */ + [deprecated] short show(); + + /** + * Opens the time dialog asynchronously. + * The passed-in object's done method will be called upon completion. + */ + void open(in nsITimePickerShownCallback aTimePickerShownCallback); +}; diff --git a/widget/nsTimePickerProxy.cpp b/widget/nsTimePickerProxy.cpp new file mode 100644 index 0000000000..3cc2ca1be6 --- /dev/null +++ b/widget/nsTimePickerProxy.cpp @@ -0,0 +1,89 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsTimePickerProxy.h" +#include "nsComponentManagerUtils.h" +#include "mozilla/dom/TabChild.h" + +using namespace mozilla::dom; + +NS_IMPL_ISUPPORTS(nsTimePickerProxy, nsITimePicker) + +nsTimePickerProxy::nsTimePickerProxy() +{ +} + +nsTimePickerProxy::~nsTimePickerProxy() +{ +} + +NS_IMETHODIMP +nsTimePickerProxy::Init(nsIDOMWindow* aParent, const nsAString& aTitle) +{ + TabChild* tabChild = TabChild::GetFrom(aParent); + if (!tabChild) { + return NS_ERROR_FAILURE; + } + + MOZ_CRASH("Time picker not implemented for e10s"); + + mParent = do_QueryInterface(aParent); + if (!mParent->IsInnerWindow()) { + mParent = mParent->GetCurrentInnerWindow(); + } + + NS_ADDREF_THIS(); + tabChild->SendPTimePickerConstructor(nsString(aTitle)); + return NS_OK; +} + +void +nsTimePickerProxy::InitNative(nsIWidget* aParent, const nsAString& aTitle) +{ +} + +NS_IMETHODIMP +nsTimePickerProxy::Open(nsITimePickerShownCallback* aCallback) +{ + mCallback = aCallback; + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsTimePickerProxy::Show(int16_t* aReturn) +{ + MOZ_ASSERT(false, "Show is unimplemented; use Open"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsTimePickerProxy::GetDefaultTime(nsAString &aDefaultTime) {return NS_ERROR_NOT_IMPLEMENTED;} +NS_IMETHODIMP nsTimePickerProxy::SetDefaultTime(const nsAString &aDefaultTime) {return NS_ERROR_NOT_IMPLEMENTED;} +NS_IMETHODIMP nsTimePickerProxy::GetMinTime(nsAString &aMinTime) {return NS_ERROR_NOT_IMPLEMENTED;} +NS_IMETHODIMP nsTimePickerProxy::SetMinTime(const nsAString &aMinTime) {return NS_ERROR_NOT_IMPLEMENTED;} +NS_IMETHODIMP nsTimePickerProxy::GetMaxTime(nsAString &aMaxTime) {return NS_ERROR_NOT_IMPLEMENTED;}; +NS_IMETHODIMP nsTimePickerProxy::SetMaxTime(const nsAString &aMaxTime) {return NS_ERROR_NOT_IMPLEMENTED;} +NS_IMETHODIMP nsTimePickerProxy::GetStep(double *aStep) {return NS_ERROR_NOT_IMPLEMENTED;} +NS_IMETHODIMP nsTimePickerProxy::SetStep(const double aStep) {return NS_ERROR_NOT_IMPLEMENTED;} +NS_IMETHODIMP nsTimePickerProxy::GetSelectedTime(nsAString &aSelectedTime) {return NS_ERROR_NOT_IMPLEMENTED;} + +bool +nsTimePickerProxy::Recv__delete__(const nsString& time, const int16_t& aResult) +{ + if (mCallback) { + mCallback->Done(aResult); + mCallback = nullptr; + } + + return true; +} + +bool +nsTimePickerProxy::RecvUpdate(const nsString& time) +{ + MOZ_CRASH("unimplemented"); + return false; +} diff --git a/widget/nsTimePickerProxy.h b/widget/nsTimePickerProxy.h new file mode 100644 index 0000000000..aabab60713 --- /dev/null +++ b/widget/nsTimePickerProxy.h @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef NSTIMEPICKERPROXY_H +#define NSTIMEPICKERPROXY_H + +#include "nsBaseTimePicker.h" +#include "nsString.h" +#include "nsIURI.h" +#include "nsTArray.h" +#include "nsCOMArray.h" + +#include "mozilla/dom/PTimePickerChild.h" + +class nsIWidget; +class nsIFile; +class nsPIDOMWindow; + +namespace mozilla { +namespace dom { +class File; +} // namespace dom +} // namespace mozilla + +/* + + This class creates a proxy time picker to be used in content processes. + The time picker just collects the initialization data and when Show() is + called, remotes everything to the chrome process which in turn can show a + platform specific time picker. + + I'm not sure why I'm implementing this for TenFourFox given that we'll never + run in e10s, but anyway. + +*/ +class nsTimePickerProxy : public nsBaseTimePicker, + public mozilla::dom::PTimePickerChild +{ +public: + nsTimePickerProxy(); + + NS_DECL_ISUPPORTS + + // nsITimePicker + NS_IMETHODIMP Init(nsIDOMWindow* aParent, const nsAString& aTitle) override; + NS_IMETHODIMP Open(nsITimePickerShownCallback* aCallback) override; + NS_IMETHODIMP Show(int16_t *_retval) override; + NS_IMETHODIMP GetDefaultTime(nsAString &aDefaultTime) override; + NS_IMETHODIMP SetDefaultTime(const nsAString &aDefaultTime) override; + NS_IMETHODIMP GetMinTime(nsAString &aMinTime) override; + NS_IMETHODIMP SetMinTime(const nsAString &aMinTime) override; + NS_IMETHODIMP GetMaxTime(nsAString &aMaxTime) override; + NS_IMETHODIMP SetMaxTime(const nsAString &aMaxTime) override; + NS_IMETHODIMP GetStep(double *aStep) override; + NS_IMETHODIMP SetStep(const double aStep) override; + NS_IMETHODIMP GetSelectedTime(nsAString &aSelectedTime); + + // PTimePickerChild + virtual bool Recv__delete__(const nsString& time, const int16_t& aResult); + virtual bool RecvUpdate(const nsString& time); + +private: + ~nsTimePickerProxy(); + void InitNative(nsIWidget*, const nsAString&) override; + + nsCOMPtr mCallback; +}; + +#endif // NSTIMEPICKERPROXY_H diff --git a/widget/nsWidgetsCID.h b/widget/nsWidgetsCID.h index cd0cd0b3fe..4ae12d0243 100644 --- a/widget/nsWidgetsCID.h +++ b/widget/nsWidgetsCID.h @@ -29,6 +29,11 @@ { 0xbd57cee8, 0x1dd1, 0x11b2, \ {0x9f, 0xe7, 0x95, 0xcf, 0x47, 0x09, 0xae, 0xa4} } +/* bd57cee8-1dd1-11b2-9fe7-95cf4709aea5 */ +#define NS_TIMEPICKER_CID \ +{ 0xbd57cee8, 0x1dd1, 0x11b2, \ + {0x9f, 0xe7, 0x95, 0xcf, 0x47, 0x09, 0xae, 0xa5} } + /* e221df9b-3d66-4045-9a66-5720949f8d10 */ #define NS_APPLICATIONCHOOSER_CID \ { 0xe221df9b, 0x3d66, 0x4045, \