Skip to content

Instantly share code, notes, and snippets.

@xim
Forked from anonymous/autohide-test.pro
Created March 16, 2018 20:35
Show Gist options
  • Save xim/ee56564f425151ea2fa70f730d644873 to your computer and use it in GitHub Desktop.
Save xim/ee56564f425151ea2fa70f730d644873 to your computer and use it in GitHub Desktop.
autohide-test
*.user
Makefile*
.qmake.stash
release
debug
*.swp
*~
QT += widgets
TARGET = autohide-test
TEMPLATE = app
SOURCES += \
main.cpp \
mainwindow.cpp \
HEADERS += \
mainwindow.h \
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#include "mainwindow.h"
#include <QApplication>
#include <QKeyEvent>
#include <QLabel>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
ahMenuBar = new AutoHidingMenuBar;
setMenuBar(ahMenuBar);
#if defined(USE_HIDE)
#elif defined(USE_SETMAXHEIGHT) || defined(USE_NOTHING)
ahMenuBar->show();
#else
#error "missing implementation?"
#endif
ahMenuBar->setVisibleCustom(false);
auto fileMenu = menuBar()->addMenu("&File");
fileMenu->addAction("&Quit", qApp, &QCoreApplication::quit, QKeySequence::Quit);
fileMenu->addAction("Q&uit2", qApp, &QCoreApplication::quit, QKeySequence::Close);
auto viewMenu = menuBar()->addMenu("&View");
viewMenu->addAction("&Quit", qApp, &QCoreApplication::quit, QKeySequence::HelpContents);
viewMenu->addAction("Q&uit2", qApp, &QCoreApplication::quit, QKeySequence::FullScreen);
setCentralWidget(new QLabel("No can has contents"));
centralWidget()->setFocusPolicy(Qt::StrongFocus);
}
MainWindow::~MainWindow()
{
}
#if defined(USE_HIDE)
void MainWindow::keyPressEvent(QKeyEvent *event) {
if ((!event->key() || event->key() == Qt::Key_Alt) && event->modifiers() == Qt::AltModifier)
lastWasAltPress = true;
else
lastWasAltPress = false;
QMainWindow::keyPressEvent(event);
}
void MainWindow::keyReleaseEvent(QKeyEvent *event) {
if (lastWasAltPress && event->key() == Qt::Key_Alt && event->modifiers() == Qt::NoModifier) {
if (ahMenuBar->isVisible()) {
qDebug("Hiding after alt key press and visible");
ahMenuBar->hide();
} else {
qDebug("Showing after alt key press");
ahMenuBar->show();
}
lastWasAltPress = false;
}
QMainWindow::keyReleaseEvent(event);
}
#endif
AutoHidingMenuBar::AutoHidingMenuBar() : QMenuBar() {
connect(qApp, &QApplication::focusChanged, this, &AutoHidingMenuBar::focusChanged);
}
bool AutoHidingMenuBar::isVisibleCustom() {
#if defined(USE_HIDE)
return isVisible();
#elif defined(USE_SETMAXHEIGHT)
return maximumHeight() != 0;
#elif defined(USE_NOTHING)
return true;
#else
#error "missing implementation?"
#endif
}
void AutoHidingMenuBar::setVisibleCustom(bool visible) {
#if defined(USE_HIDE)
if (visible)
show();
else
hide();
#elif defined(USE_SETMAXHEIGHT)
if (visible) {
auto action = activeAction();
setMaximumHeight(100);
if (action) {
// XXX This is a bit of a hack. We could do
// QCoreApplication::processEvents();
// setActiveAction(action);
// with almost the same effect, but then we *open* the first menu on single alt press...
auto evt = new QMouseEvent(QEvent::MouseMove, actionGeometry(action).center(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
QCoreApplication::postEvent(this, evt);
}
} else
setMaximumHeight(0);
#elif defined(USE_NOTHING)
Q_UNUSED(visible)
#else
#error "missing implementation?"
#endif
}
void AutoHidingMenuBar::focusChanged(QWidget *, QWidget * focus) {
bool inFocus = hasFocus() || isAncestorOf(focus) || hasFocusedChild();
if (inFocus && !isVisibleCustom()) {
qDebug("Came into focus, should appear.");
setVisibleCustom(true);
} else if (!inFocus && isVisibleCustom()) {
qDebug("Lost focus on menu bar, should hide.");
setVisibleCustom(false);
}
}
bool AutoHidingMenuBar::hasFocusedChild() {
QObjectList queue{children()};
while (!queue.empty()) {
auto child = queue.takeFirst();
auto widget = dynamic_cast<QWidget *>(child);
if (widget && widget->hasFocus())
return true;
queue.append(child->children());
}
return false;
}
#if defined(DEBUG_EVENTS)
bool AutoHidingMenuBar::eventFilter(QObject * obj, QEvent * event) {
if (event->type() == QEvent::HoverMove) {
auto hoverEvent = dynamic_cast<QHoverEvent *>(event);
qDebug("Hover at %dx%d", hoverEvent->pos().x(), hoverEvent->pos().y());
}
return QMenuBar::eventFilter(obj, event);
}
#endif
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMenuBar>
//#define USE_HIDE
#define USE_SETMAXHEIGHT
//#define USE_NOTHING
//#define DEBUG_EVENTS
class AutoHidingMenuBar : public QMenuBar {
Q_OBJECT
public:
AutoHidingMenuBar();
bool isVisibleCustom();
void setVisibleCustom(bool visible);
#if defined(DEBUG_EVENTS)
protected:
bool eventFilter(QObject *, QEvent *) Q_DECL_OVERRIDE;
#endif
private slots:
void focusChanged(QWidget *from, QWidget *to);
private:
bool hasFocusedChild();
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
#if defined(USE_HIDE)
protected:
void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE;
void keyReleaseEvent(QKeyEvent *) Q_DECL_OVERRIDE;
private:
bool lastWasAltPress = false;
#endif
private:
AutoHidingMenuBar * ahMenuBar;
};
#endif // MAINWINDOW_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment