#405: implement interface, widget, plumbing for time picker

This commit is contained in:
Cameron Kaiser 2018-06-30 09:24:55 -07:00
parent 52f6389cad
commit 1c5fbc3107
24 changed files with 1156 additions and 3 deletions

View File

@ -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"

View File

@ -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.

27
dom/ipc/PTimePicker.ipdl Normal file
View File

@ -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

View File

@ -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<nsTimePickerProxy*>(actor);
NS_RELEASE(datePicker);
return true;
}
auto
TabChild::AllocPIndexedDBPermissionRequestChild(const Principal& aPrincipal)
-> PIndexedDBPermissionRequestChild*

View File

@ -425,6 +425,11 @@ public:
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;

View File

@ -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*

View File

@ -368,6 +368,10 @@ public:
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;

View File

@ -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<nsIDOMWindow> 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();
}
}

View File

@ -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<TimePickerShownCallback> mCallback;
nsCOMPtr<nsITimePicker> mPicker;
nsString mTitle;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_TimePickerParent_h

View File

@ -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')

View File

@ -69,6 +69,7 @@ SOURCES += [
'nsDatePicker.mm',
'nsDragService.mm',
'nsNativeThemeCocoa.mm',
'nsTimePicker.mm',
]
if not CONFIG['RELEASE_BUILD'] or CONFIG['MOZ_DEBUG']:

View File

@ -80,6 +80,8 @@
- (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)

View File

@ -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_

View File

@ -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 <Cocoa/Cocoa.h>
#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<nsIStringBundle> 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<nsIStringBundleService> 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<const unichar*>(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;
}

View File

@ -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 @@ using namespace mozilla::widget;
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_WINDOW_CID);
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 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
{ &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 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
{ "@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,

View File

@ -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'):

View File

@ -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<nsITimePicker> mTimePicker;
RefPtr<nsITimePickerShownCallback> 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<nsIWidget> 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<nsIRunnable> filePickerEvent =
new AsyncShowTimePicker(this, aCallback);
return NS_DispatchToMainThread(filePickerEvent);
}

37
widget/nsBaseTimePicker.h Normal file
View File

@ -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<nsPIDOMWindow> mParent;
};
#endif // nsBaseTimePicker_h__

View File

@ -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 }

View File

@ -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);
};

92
widget/nsITimePicker.idl Normal file
View File

@ -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);
};

View File

@ -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;
}

View File

@ -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<nsITimePickerShownCallback> mCallback;
};
#endif // NSTIMEPICKERPROXY_H

View File

@ -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, \