This code reproduces QTBUG-49238.
Last active
November 4, 2015 18:08
-
-
Save xim/151e50088d06ee21b643 to your computer and use it in GitHub Desktop.
QTBUG-49238
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "dialog.h" | |
#include <QCoreApplication> | |
#include <QHBoxLayout> | |
#include <QTextEdit> | |
static Dialog *dialog = nullptr; | |
Dialog::Dialog() | |
: QDialog() | |
{ | |
dialog = this; | |
QLayout *layout = new QHBoxLayout(this); | |
label = new QTextEdit; | |
addText("Status updates for the application will be shown here. Close dialog to exit."); | |
layout->addWidget(label); | |
layout->setContentsMargins(10, 10, 10, 10); | |
} | |
void Dialog::addText(const QString &text) { | |
label->append(text); | |
} | |
void logToDialog(const QString &text) { | |
qDebug("%s", text.toLocal8Bit().constData()); | |
dialog->addText(text); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef DIALOG_H | |
#define DIALOG_H | |
#include <QDialog> | |
class QTextEdit; | |
class Dialog : public QDialog | |
{ | |
Q_OBJECT | |
public: | |
Dialog(); | |
void addText(const QString &); | |
private: | |
QTextEdit *label; | |
}; | |
void logToDialog(const QString &); | |
#endif // DIALOG_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "dialog.h" | |
#include "sleeplistener.h" | |
#include <QApplication> | |
QDialog *testObject = nullptr; | |
static void printDestruction() { | |
logToDialog("Destroyed object."); | |
} | |
static void createNewObject() { | |
testObject = new QDialog; | |
logToDialog("Created object."); | |
QObject::connect(testObject, &QObject::destroyed, qApp, &printDestruction); | |
} | |
static void deleteObject() { | |
logToDialog("Queueing object delete."); | |
testObject->deleteLater(); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
QApplication a(argc, argv); | |
Dialog w; | |
SleepListener listener; | |
createNewObject(); | |
QObject::connect(&listener, &SleepListener::willSleep, qApp, &deleteObject); | |
QObject::connect(&listener, &SleepListener::didWake, qApp, &createNewObject); | |
QObject::connect(qApp, &QCoreApplication::aboutToQuit, qApp, &deleteObject); | |
w.show(); | |
return a.exec(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#------------------------------------------------- | |
# | |
# Project created by QtCreator 2015-11-04T17:57:59 | |
# | |
#------------------------------------------------- | |
QT += core gui widgets | |
TARGET = SleepDelete | |
TEMPLATE = app | |
CONFIG += c++11 | |
SOURCES += \ | |
dialog.cpp \ | |
main.cpp | |
OBJECTIVE_SOURCES += \ | |
sleeplistener.mm | |
HEADERS += \ | |
dialog.h \ | |
sleeplistener.h | |
QMAKE_LFLAGS += -framework IOKit -framework Cocoa | |
QMAKE_MAC_SDK = macosx10.11 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SLEEPLISTENER_H | |
#define SLEEPLISTENER_H | |
#include <QObject> | |
#include <IOKit/IOMessage.h> | |
#include <IOKit/pwr_mgt/IOPMLib.h> | |
class SleepListener : public QObject { | |
Q_OBJECT | |
public: | |
SleepListener(); | |
~SleepListener(); | |
SleepListener(const SleepListener &) = delete; | |
SleepListener &operator=(const SleepListener &) = delete; | |
signals: | |
void willSleep(); | |
void didWake(); | |
public: | |
io_connect_t root_port; // Root power domain IOService connection | |
IONotificationPortRef notifyPortRef; // Notification port allocated by IORegisterForSystemPower | |
io_object_t notifierObject; // Notifier object, used to deregister | |
}; | |
#endif // SLEEPLISTENER_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "dialog.h" | |
#include "sleeplistener.h" | |
#include <mach/mach_port.h> | |
#include <mach/mach_interface.h> | |
#include <mach/mach_init.h> | |
namespace { | |
void sleepCallback(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) { | |
Q_UNUSED(service) | |
SleepListener *listener = reinterpret_cast<SleepListener *>(refCon); | |
switch (messageType) { | |
case kIOMessageCanSystemSleep: | |
logToDialog("System wants to enter idle sleep."); | |
IOAllowPowerChange(listener->root_port, (long) messageArgument); | |
break; | |
case kIOMessageSystemWillSleep: | |
logToDialog("System WILL sleep."); | |
emit listener->willSleep(); | |
logToDialog("Allowing sleep."); | |
IOAllowPowerChange(listener->root_port, (long) messageArgument); | |
break; | |
case kIOMessageSystemWillPowerOn: | |
logToDialog("System is waking up from sleep."); | |
break; | |
case kIOMessageSystemHasPoweredOn: | |
logToDialog("System has powered on."); | |
emit listener->didWake(); | |
logToDialog("System has woken up from sleep."); | |
break; | |
} | |
} | |
} | |
SleepListener::SleepListener() | |
{ | |
// Register to receive system sleep notifications | |
root_port = IORegisterForSystemPower(this, ¬ifyPortRef, | |
sleepCallback, ¬ifierObject); | |
if (!root_port) { | |
logToDialog("Could not register for sleep notifications."); | |
return; | |
} | |
// Add the notification port to the application runloop | |
CFRunLoopAddSource(CFRunLoopGetCurrent(), | |
IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes); | |
} | |
SleepListener::~SleepListener() { | |
// Remove the sleep notification port from the application runloop | |
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), | |
IONotificationPortGetRunLoopSource(notifyPortRef), | |
kCFRunLoopCommonModes); | |
// Deregister for system sleep notifications | |
IODeregisterForSystemPower(¬ifierObject); | |
// IORegisterForSystemPower implicitly opens the Root Power Domain IOService | |
// so we close it here | |
IOServiceClose(root_port); | |
// Destroy the notification port allocated by IORegisterForSystemPower | |
IONotificationPortDestroy(notifyPortRef); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment