Commit 495fa523 authored by abbycin's avatar abbycin

add error handling

NOTE: error message in Linux is hardcoded, since there's no way to get error from xcb_generic_error_t
parent 6030c156
...@@ -26,7 +26,7 @@ void QGlobalShortcut::initialize() { ...@@ -26,7 +26,7 @@ void QGlobalShortcut::initialize() {
} }
QGlobalShortcut::~QGlobalShortcut() { QGlobalShortcut::~QGlobalShortcut() {
unsetKey();
} }
QKeySequence QGlobalShortcut::key() const QKeySequence QGlobalShortcut::key() const
...@@ -34,7 +34,7 @@ QKeySequence QGlobalShortcut::key() const ...@@ -34,7 +34,7 @@ QKeySequence QGlobalShortcut::key() const
return keyseq_; return keyseq_;
} }
void QGlobalShortcut::setKey(const QKeySequence& keyseq) bool QGlobalShortcut::setKey(const QKeySequence& keyseq)
{ {
if (!keyseq_.isEmpty()) { if (!keyseq_.isEmpty()) {
unsetKey(); unsetKey();
...@@ -43,22 +43,44 @@ void QGlobalShortcut::setKey(const QKeySequence& keyseq) ...@@ -43,22 +43,44 @@ void QGlobalShortcut::setKey(const QKeySequence& keyseq)
if (shortcuts_.count(keyid) == 0) { if (shortcuts_.count(keyid) == 0) {
quint32 keycode = toNativeKeycode(getKey(keyseq)); quint32 keycode = toNativeKeycode(getKey(keyseq));
quint32 mods = toNativeModifiers(getMods(keyseq)); quint32 mods = toNativeModifiers(getMods(keyseq));
registerKey(keycode, mods, keyid); #ifdef Q_OS_WIN
if(!registerKey(keycode, mods, keyid)) {
error(getErrorMsg());
return false;
}
#else
if(!registerKey(keycode, mods, keyid)) {
error("Hotkey already set");
return false;
}
#endif
} }
this->keyseq_ = keyseq; this->keyseq_ = keyseq;
shortcuts_.insert(keyid, this); shortcuts_.insert(keyid, this);
return true;
} }
void QGlobalShortcut::unsetKey() { bool QGlobalShortcut::unsetKey() {
quint32 keyid = calcId(keyseq_); quint32 keyid = calcId(keyseq_);
if (shortcuts_.remove(keyid, this) > 0) { if (shortcuts_.remove(keyid, this) > 0) {
if (shortcuts_.count(keyid) == 0) { if (shortcuts_.count(keyid) == 0) {
quint32 keycode = toNativeKeycode(getKey(keyseq_)); quint32 keycode = toNativeKeycode(getKey(keyseq_));
quint32 mods = toNativeModifiers(getMods(keyseq_)); quint32 mods = toNativeModifiers(getMods(keyseq_));
unregisterKey(keycode, mods, keyid); #ifdef Q_OS_WIN
if(!unregisterKey(keycode, mods, keyid)) {
error(getErrorMsg());
return false;
}
#else
if(!unregisterKey(keycode, mods, keyid)) {
error("No hotkey set");
return false;
}
#endif
keyseq_ = QKeySequence(); // clear keyseq_ = QKeySequence(); // clear
} }
} }
return true;
} }
bool QGlobalShortcut::activate(quint32 id) { bool QGlobalShortcut::activate(quint32 id) {
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
class GLOBAL_HOTKEY_EXPORT QGlobalShortcut : public QObject { class GLOBAL_HOTKEY_EXPORT QGlobalShortcut : public QObject {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QKeySequence key READ key WRITE setKey) Q_PROPERTY(QKeySequence key READ key WRITE setKey)
//Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
private: private:
class QGlobalShortcutEventFilter : public QAbstractNativeEventFilter { class QGlobalShortcutEventFilter : public QAbstractNativeEventFilter {
...@@ -24,21 +24,21 @@ public: ...@@ -24,21 +24,21 @@ public:
bool nativeEventFilter(const QByteArray& event_type, void* message, long* result); bool nativeEventFilter(const QByteArray& event_type, void* message, long* result);
QKeySequence key() const; QKeySequence key() const;
void setKey(const QKeySequence& keyseq); // you must unset hot key explicitly
void unsetKey(); bool setKey(const QKeySequence& keyseq);
//bool isEnabled() const; void setEnabled(bool on); bool unsetKey();
signals: signals:
void activated(); void activated();
void error(QString);
private: private:
QKeySequence keyseq_; QKeySequence keyseq_;
void initialize(); void initialize();
private: private:
static QGlobalShortcutEventFilter global_shortcut_event_; static QGlobalShortcutEventFilter global_shortcut_event_;
/* quint32 keyid
QGlobalShortcut* shortcut */
static QMultiHash<quint32, QGlobalShortcut*> shortcuts_; static QMultiHash<quint32, QGlobalShortcut*> shortcuts_;
static bool activate(quint32 id); static bool activate(quint32 id);
static inline quint32 calcId(const QKeySequence& keyseq); static inline quint32 calcId(const QKeySequence& keyseq);
...@@ -47,6 +47,9 @@ private: ...@@ -47,6 +47,9 @@ private:
static inline Qt::KeyboardModifiers getMods(const QKeySequence& keyseq); static inline Qt::KeyboardModifiers getMods(const QKeySequence& keyseq);
static quint32 toNativeKeycode(Qt::Key k); static quint32 toNativeKeycode(Qt::Key k);
static quint32 toNativeModifiers(Qt::KeyboardModifiers m); static quint32 toNativeModifiers(Qt::KeyboardModifiers m);
static void registerKey(quint32 k, quint32 m, quint32 id); #ifdef Q_OS_WIN
static void unregisterKey(quint32 k, quint32 m, quint32 id); static QString getErrorMsg();
#endif
static bool registerKey(quint32 k, quint32 m, quint32 id);
static bool unregisterKey(quint32 k, quint32 m, quint32 id);
}; };
...@@ -106,10 +106,26 @@ quint32 QGlobalShortcut::toNativeModifiers(Qt::KeyboardModifiers m) { ...@@ -106,10 +106,26 @@ quint32 QGlobalShortcut::toNativeModifiers(Qt::KeyboardModifiers m) {
return mods; return mods;
} }
void QGlobalShortcut::registerKey(quint32 k, quint32 m, quint32 id) { QString QGlobalShortcut::getErrorMsg() {
RegisterHotKey(NULL, id, m, k); DWORD errorMessageID = ::GetLastError();
if(errorMessageID == 0) {
return {};
}
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, LANG_USER_DEFAULT,
(LPSTR)&messageBuffer, 0, NULL);
std::string message{messageBuffer, size};
LocalFree(messageBuffer);
return QString::fromLocal8Bit(message.data(), message.size());
}
bool QGlobalShortcut::registerKey(quint32 k, quint32 m, quint32 id) {
return RegisterHotKey(NULL, id, m, k);
} }
void QGlobalShortcut::unregisterKey(quint32 /*k*/, quint32 /*m*/, quint32 id) { bool QGlobalShortcut::unregisterKey(quint32 /*k*/, quint32 /*m*/, quint32 id) {
UnregisterHotKey(NULL, id); return UnregisterHotKey(NULL, id);
} }
...@@ -6,13 +6,13 @@ ...@@ -6,13 +6,13 @@
#include <X11/keysym.h> #include <X11/keysym.h>
bool QGlobalShortcut::QGlobalShortcutEventFilter::nativeEventFilter( bool QGlobalShortcut::QGlobalShortcutEventFilter::nativeEventFilter(
const QByteArray& eventType, void* message, long* result) const QByteArray& /*eventType*/, void* message, long*)
{ {
xcb_generic_event_t* e = static_cast<xcb_generic_event_t*>(message); xcb_generic_event_t* e = static_cast<xcb_generic_event_t*>(message);
if ((e->response_type & ~0x80) == XCB_KEY_PRESS) { if ((e->response_type & ~0x80) == XCB_KEY_PRESS) {
xcb_key_press_event_t* ke = (xcb_key_press_event_t*)e; xcb_key_press_event_t* ke = (xcb_key_press_event_t*)e;
xcb_get_keyboard_mapping_reply_t rep; xcb_get_keyboard_mapping_reply_t rep;
xcb_keysym_t* k = xcb_get_keyboard_mapping_keysyms(&rep); /*xcb_keysym_t* k = */xcb_get_keyboard_mapping_keysyms(&rep);
quint32 keycode = ke->detail; quint32 keycode = ke->detail;
quint32 mods = ke->state & (ShiftMask|ControlMask|Mod1Mask|Mod3Mask); quint32 mods = ke->state & (ShiftMask|ControlMask|Mod1Mask|Mod3Mask);
return activate(calcId(keycode, mods)); return activate(calcId(keycode, mods));
...@@ -113,11 +113,21 @@ quint32 QGlobalShortcut::toNativeModifiers(Qt::KeyboardModifiers m) { ...@@ -113,11 +113,21 @@ quint32 QGlobalShortcut::toNativeModifiers(Qt::KeyboardModifiers m) {
return mods; return mods;
} }
void QGlobalShortcut::registerKey(quint32 k, quint32 m, quint32 id) { bool QGlobalShortcut::registerKey(quint32 k, quint32 m, quint32 /*id*/) {
xcb_grab_key(QX11Info::connection(), 1, QX11Info::appRootWindow(), xcb_void_cookie_t r = xcb_grab_key_checked(QX11Info::connection(), 1, QX11Info::appRootWindow(),
m, k, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); m, k, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
auto rsp = xcb_request_check(QX11Info::connection(), r);
if(!rsp) {
return true;
}
return rsp->error_code != 10;
} }
void QGlobalShortcut::unregisterKey(quint32 k, quint32 m, quint32 id) { bool QGlobalShortcut::unregisterKey(quint32 k, quint32 m, quint32 /*id*/) {
xcb_ungrab_key(QX11Info::connection(), k, QX11Info::appRootWindow(), m); xcb_void_cookie_t r = xcb_ungrab_key_checked(QX11Info::connection(), k, QX11Info::appRootWindow(), m);
auto rsp = xcb_request_check(QX11Info::connection(), r);
if(!rsp) {
return true;
}
return rsp->error_code != 10;
} }
...@@ -69,8 +69,6 @@ void MainWindow::initEditor() ...@@ -69,8 +69,6 @@ void MainWindow::initEditor()
connect(acc, &QPushButton::clicked, mEdit, [this] { connect(acc, &QPushButton::clicked, mEdit, [this] {
mEdit->hide(); mEdit->hide();
mFull->setKey();
mHide->setKey();
}); });
connect(rej, &QPushButton::clicked, mEdit, [this] { connect(rej, &QPushButton::clicked, mEdit, [this] {
mHide->clear(); mHide->clear();
...@@ -90,6 +88,10 @@ void MainWindow::initEditor() ...@@ -90,6 +88,10 @@ void MainWindow::initEditor()
this->hide(); this->hide();
} }
}); });
connect(mHide, &KeyEdit::error, [this](QString msg) {
QMessageBox::critical(this, "Error", msg);
mHide->clear();
});
connect(mFull, &KeyEdit::actived, [this] { connect(mFull, &KeyEdit::actived, [this] {
if(this->isFullScreen()) if(this->isFullScreen())
{ {
...@@ -100,10 +102,20 @@ void MainWindow::initEditor() ...@@ -100,10 +102,20 @@ void MainWindow::initEditor()
this->showFullScreen(); this->showFullScreen();
} }
}); });
connect(mFull, &KeyEdit::error, [this](QString msg) {
QMessageBox::critical(this, "Error", msg);
});
mEdit->setLayout(g); mEdit->setLayout(g);
mEdit->resize(mEdit->sizeHint()); mEdit->resize(mEdit->sizeHint());
mEdit->hide(); mEdit->hide();
#ifdef Q_OS_WIN
// test conflit with QQ
mHide->setKey(QKeySequence::fromString("Ctrl+Alt+A"));
#else
// test conflit with search
mHide->setKey(QKeySequence::fromString("Alt+Space"));
#endif
} }
KeyEdit::KeyEdit(QWidget *parent) KeyEdit::KeyEdit(QWidget *parent)
...@@ -113,6 +125,10 @@ KeyEdit::KeyEdit(QWidget *parent) ...@@ -113,6 +125,10 @@ KeyEdit::KeyEdit(QWidget *parent)
connect(mGhk, &QGlobalShortcut::activated, [this] { connect(mGhk, &QGlobalShortcut::activated, [this] {
this->actived(mGhk->key()); this->actived(mGhk->key());
}); });
connect(mGhk, &QGlobalShortcut::error, this, &KeyEdit::error);
connect(this, &KeyEdit::editingFinished, [this] {
mGhk->setKey(this->keySequence());
});
} }
KeyEdit::~KeyEdit() KeyEdit::~KeyEdit()
...@@ -122,12 +138,12 @@ KeyEdit::~KeyEdit() ...@@ -122,12 +138,12 @@ KeyEdit::~KeyEdit()
void KeyEdit::clear() void KeyEdit::clear()
{ {
mGhk->unsetKey();
QKeySequenceEdit::clear(); QKeySequenceEdit::clear();
mGhk->unsetKey();
} }
void KeyEdit::setKey() void KeyEdit::setKey(QKeySequence key)
{ {
mGhk->unsetKey(); QKeySequenceEdit::setKeySequence(key);
mGhk->setKey(this->keySequence()); mGhk->setKey(key);
} }
...@@ -16,10 +16,11 @@ public: ...@@ -16,10 +16,11 @@ public:
void clear(); void clear();
void setKey(); void setKey(QKeySequence key);
signals: signals:
void actived(QKeySequence key); void actived(QKeySequence key);
void error(QString);
private: private:
QGlobalShortcut* mGhk; QGlobalShortcut* mGhk;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment