Fix notifications hiding on Linux.

Regression was introduced in 3372dfcd3e.

Only when platform-specific code can give us the global time of the
last user input event we rely on idle time for notifications hiding.

Fixes #5791.
This commit is contained in:
John Preston 2019-03-14 21:59:10 +04:00
parent a5d1fbff98
commit 0df628dc7a
12 changed files with 75 additions and 100 deletions

View File

@ -860,7 +860,9 @@ void Application::updateNonIdle() {
}
crl::time Application::lastNonIdleTime() const {
return std::max(Platform::LastUserInputTime(), _lastNonIdleTime);
return std::max(
Platform::LastUserInputTime().value_or(0),
_lastNonIdleTime);
}
rpl::producer<bool> Application::passcodeLockChanges() const {

View File

@ -193,10 +193,6 @@ void psDeleteDir(const QString &dir) {
_removeDirectory(dir);
}
bool psIdleSupported() {
return false;
}
void psActivateProcess(uint64 pid) {
// objc_activateProgram();
}
@ -435,10 +431,6 @@ bool OpenSystemSettings(SystemSettingsType type) {
return true;
}
crl::time LastUserInputTime() {
return 0LL;
}
namespace ThirdParty {
void start() {

View File

@ -33,7 +33,9 @@ inline void ReInitOnTopPanel(QWidget *panel) {
QString CurrentExecutablePath(int argc, char *argv[]);
crl::time LastUserInputTime();
inline std::optional<crl::time> LastUserInputTime() {
return std::nullopt;
}
} // namespace Platform
@ -51,8 +53,6 @@ void psWriteDump();
void psDeleteDir(const QString &dir);
bool psIdleSupported();
QStringList psInitLogs();
void psClearInitLogs();

View File

@ -19,8 +19,6 @@ inline bool TranslucentWindowsSupported(QPoint globalPosition) {
QString CurrentExecutablePath(int argc, char *argv[]);
crl::time LastUserInputTime();
void RemoveQuarantine(const QString &path);
namespace ThirdParty {
@ -52,8 +50,6 @@ void psWriteDump();
void psDeleteDir(const QString &dir);
bool psIdleSupported();
QStringList psInitLogs();
void psClearInitLogs();

View File

@ -90,10 +90,6 @@ void psDeleteDir(const QString &dir) {
objc_deleteDir(dir);
}
bool psIdleSupported() {
return objc_idleSupported();
}
QStringList psInitLogs() {
return _initLogs;
}
@ -255,9 +251,58 @@ bool OpenSystemSettings(SystemSettingsType type) {
return true;
}
crl::time LastUserInputTime() {
auto idleTime = 0LL;
return objc_idleTime(idleTime) ? (crl::now() - crl::time(idleTime)) : 0LL;
// Taken from https://github.com/trueinteractions/tint/issues/53.
std::optional<crl::time> LastUserInputTime() {
CFMutableDictionaryRef properties = 0;
CFTypeRef obj;
mach_port_t masterPort;
io_iterator_t iter;
io_registry_entry_t curObj;
IOMasterPort(MACH_PORT_NULL, &masterPort);
/* Get IOHIDSystem */
IOServiceGetMatchingServices(masterPort, IOServiceMatching("IOHIDSystem"), &iter);
if (iter == 0) {
return std::nullopt;
} else {
curObj = IOIteratorNext(iter);
}
if (IORegistryEntryCreateCFProperties(curObj, &properties, kCFAllocatorDefault, 0) == KERN_SUCCESS && properties != NULL) {
obj = CFDictionaryGetValue(properties, CFSTR("HIDIdleTime"));
CFRetain(obj);
} else {
return std::nullopt;
}
uint64 err = ~0L, idleTime = err;
if (obj) {
CFTypeID type = CFGetTypeID(obj);
if (type == CFDataGetTypeID()) {
CFDataGetBytes((CFDataRef) obj, CFRangeMake(0, sizeof(idleTime)), (UInt8*)&idleTime);
} else if (type == CFNumberGetTypeID()) {
CFNumberGetValue((CFNumberRef)obj, kCFNumberSInt64Type, &idleTime);
} else {
// error
}
CFRelease(obj);
if (idleTime != err) {
idleTime /= 1000000; // return as ms
}
} else {
// error
}
CFRelease((CFTypeRef)properties);
IOObjectRelease(curObj);
IOObjectRelease(iter);
if (idleTime == err) {
return std::nullopt;
}
return (crl::now() - static_cast<crl::time>(idleTime));
}
} // namespace Platform

View File

@ -16,8 +16,6 @@ void objc_bringToBack(WId winId);
void objc_debugShowAlert(const QString &str);
void objc_outputDebugString(const QString &str);
bool objc_idleSupported();
bool objc_idleTime(crl::time &idleTime);
void objc_start();
void objc_ignoreApplicationActivationRightNow();

View File

@ -343,64 +343,6 @@ void objc_outputDebugString(const QString &str) {
}
}
bool objc_idleSupported() {
auto idleTime = 0LL;
return objc_idleTime(idleTime);
}
bool objc_idleTime(crl::time &idleTime) { // taken from https://github.com/trueinteractions/tint/issues/53
CFMutableDictionaryRef properties = 0;
CFTypeRef obj;
mach_port_t masterPort;
io_iterator_t iter;
io_registry_entry_t curObj;
IOMasterPort(MACH_PORT_NULL, &masterPort);
/* Get IOHIDSystem */
IOServiceGetMatchingServices(masterPort, IOServiceMatching("IOHIDSystem"), &iter);
if (iter == 0) {
return false;
} else {
curObj = IOIteratorNext(iter);
}
if (IORegistryEntryCreateCFProperties(curObj, &properties, kCFAllocatorDefault, 0) == KERN_SUCCESS && properties != NULL) {
obj = CFDictionaryGetValue(properties, CFSTR("HIDIdleTime"));
CFRetain(obj);
} else {
return false;
}
uint64 err = ~0L, result = err;
if (obj) {
CFTypeID type = CFGetTypeID(obj);
if (type == CFDataGetTypeID()) {
CFDataGetBytes((CFDataRef) obj, CFRangeMake(0, sizeof(result)), (UInt8*)&result);
} else if (type == CFNumberGetTypeID()) {
CFNumberGetValue((CFNumberRef)obj, kCFNumberSInt64Type, &result);
} else {
// error
}
CFRelease(obj);
if (result != err) {
result /= 1000000; // return as ms
}
} else {
// error
}
CFRelease((CFTypeRef)properties);
IOObjectRelease(curObj);
IOObjectRelease(iter);
if (result == err) return false;
idleTime = static_cast<crl::time>(result);
return true;
}
void objc_start() {
_sharedDelegate = [[ApplicationDelegate alloc] init];
[[NSApplication sharedApplication] setDelegate:_sharedDelegate];

View File

@ -40,8 +40,13 @@ void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCal
void OpenSystemSettingsForPermission(PermissionType type);
bool OpenSystemSettings(SystemSettingsType type);
QString SystemLanguage();
QString SystemCountry();
[[nodiscard]] QString SystemLanguage();
[[nodiscard]] QString SystemCountry();
[[nodiscard]] std::optional<crl::time> LastUserInputTime();
[[nodiscard]] inline bool LastUserInputTimeSupported() {
return LastUserInputTime().has_value();
}
namespace ThirdParty {

View File

@ -128,12 +128,6 @@ namespace {
}
}
bool psIdleSupported() {
LASTINPUTINFO lii;
lii.cbSize = sizeof(LASTINPUTINFO);
return GetLastInputInfo(&lii);
}
QStringList psInitLogs() {
return _initLogs;
}
@ -333,10 +327,12 @@ QString CurrentExecutablePath(int argc, char *argv[]) {
return QString();
}
crl::time LastUserInputTime() {
LASTINPUTINFO lii;
std::optional<crl::time> LastUserInputTime() {
auto lii = LASTINPUTINFO{ 0 };
lii.cbSize = sizeof(LASTINPUTINFO);
return GetLastInputInfo(&lii) ? (crl::now() + lii.dwTime - GetTickCount()) : 0LL;
return GetLastInputInfo(&lii)
? std::make_optional(crl::now() + lii.dwTime - GetTickCount())
: std::nullopt;
}
namespace {

View File

@ -36,8 +36,6 @@ inline void ReInitOnTopPanel(QWidget *panel) {
QString CurrentExecutablePath(int argc, char *argv[]);
crl::time LastUserInputTime();
namespace ThirdParty {
inline void start() {
@ -59,8 +57,6 @@ void psWriteDump();
void psDeleteDir(const QString &dir);
bool psIdleSupported();
QStringList psInitLogs();
void psClearInitLogs();

View File

@ -205,7 +205,7 @@ void SetupLocalPasscode(not_null<Ui::VerticalLayout*> container) {
Ui::show(Box<PasscodeBox>(true));
});
const auto label = psIdleSupported()
const auto label = Platform::LastUserInputTimeSupported()
? lng_passcode_autolock_away
: lng_passcode_autolock_inactive;
auto value = PasscodeChanges(

View File

@ -586,7 +586,10 @@ void Notification::prepareActionsCache() {
bool Notification::checkLastInput(bool hasReplyingNotifications) {
if (!_waitingForInput) return true;
if (Core::App().lastNonIdleTime() > _started) {
const auto waitForUserInput = Platform::LastUserInputTimeSupported()
? (Core::App().lastNonIdleTime() <= _started)
: false;
if (!waitForUserInput) {
_waitingForInput = false;
if (!hasReplyingNotifications) {
_hideTimer.start(st::notifyWaitLongHide);