QtPass
2.0.0
Developer documentation
Toggle main menu visibility
Loading...
Searching...
No Matches
menubarpeek.cpp
Go to the documentation of this file.
1
// SPDX-FileCopyrightText: 2026 Anne Jan Brouwer
2
// SPDX-License-Identifier: GPL-3.0-or-later
8
#include "
menubarpeek.h
"
9
#include <QAction>
10
#include <QApplication>
11
#include <QKeyEvent>
12
#include <QMainWindow>
13
#include <QMenu>
14
#include <QMenuBar>
15
#include <QTimer>
16
17
MenuBarPeek::MenuBarPeek
(QMainWindow *window, QAction *toggle)
18
: QObject(window),
m_window
(window),
m_toggle
(toggle) {
19
// Key events go to the focus widget, and an open menu is a window of its
20
// own, so the filter has to sit on the application.
21
qApp->installEventFilter(
this
);
22
connect(
m_toggle
, &QAction::toggled,
this
, [
this
] {
m_peeking
=
false
; });
23
for
(QAction *entry :
m_window
->menuBar()->actions()) {
24
if
(QMenu *menu = entry->menu()) {
25
connect(menu, &QMenu::aboutToHide,
this
,
26
&
MenuBarPeek::hideWhenNoMenuIsOpen
);
27
}
28
}
29
}
30
31
auto
MenuBarPeek::isPeeking
() const ->
bool
{
return
m_peeking
; }
32
33
auto
MenuBarPeek::eventFilter
(QObject *watched, QEvent *event) ->
bool
{
34
switch
(event->type()) {
35
case
QEvent::KeyPress:
36
onKeyPress
(watched,
static_cast<
QKeyEvent *
>
(event));
37
break
;
38
case
QEvent::KeyRelease:
39
onKeyRelease
(
static_cast<
QKeyEvent *
>
(event));
40
break
;
41
case
QEvent::MouseButtonPress:
42
if
(
m_peeking
&&
inWindow
(watched) && !
onMenuBar
(watched)) {
43
hideWhenNoMenuIsOpen
();
44
}
45
break
;
46
case
QEvent::WindowDeactivate:
47
if
(watched ==
m_window
) {
48
// Alt+Tab: the release goes to another application.
49
m_altDown
=
false
;
50
hideWhenNoMenuIsOpen
();
51
}
52
break
;
53
default
:
54
break
;
55
}
56
return
false
;
57
}
58
59
// A key event reaches the filter once for every widget it propagates to, and
60
// again as auto-repeat; m_altDown makes the second sighting a no-op.
61
void
MenuBarPeek::onKeyPress
(QObject *watched,
const
QKeyEvent *event) {
62
if
(event->key() != Qt::Key_Alt) {
63
m_altAlone
=
false
;
64
if
(event->key() == Qt::Key_Escape &&
m_peeking
) {
65
hideWhenNoMenuIsOpen
();
66
}
67
return
;
68
}
69
if
(
m_altDown
|| event->isAutoRepeat() || !
inWindow
(watched)) {
70
return
;
71
}
72
m_altDown
=
true
;
73
m_altAlone
=
true
;
74
m_shownByThisPress
=
75
!
m_peeking
&& !
m_toggle
->isChecked() && !
m_window
->menuBar()->isVisible();
76
if
(
m_shownByThisPress
) {
77
show
();
78
}
79
}
80
81
void
MenuBarPeek::onKeyRelease
(
const
QKeyEvent *event) {
82
if
(event->key() != Qt::Key_Alt || !
m_altDown
|| event->isAutoRepeat()) {
83
return
;
84
}
85
m_altDown
=
false
;
86
if
(!
m_peeking
) {
87
return
;
88
}
89
if
(
m_altAlone
&& !
m_shownByThisPress
) {
90
hide
();
// the second tap
91
}
else
if
(!
m_altAlone
) {
92
hideWhenNoMenuIsOpen
();
// Alt+something that was not a menu
93
}
94
}
95
96
auto
MenuBarPeek::inWindow
(QObject *watched)
const
->
bool
{
97
const
auto
*widget = qobject_cast<QWidget *>(watched);
98
return
widget !=
nullptr
&& widget->window() ==
m_window
;
99
}
100
101
auto
MenuBarPeek::onMenuBar
(QObject *watched)
const
->
bool
{
102
const
auto
*widget = qobject_cast<QWidget *>(watched);
103
const
QMenuBar *bar =
m_window
->menuBar();
104
return
widget == bar || bar->isAncestorOf(widget);
105
}
106
107
void
MenuBarPeek::show
() {
108
m_peeking
=
true
;
109
m_window
->menuBar()->show();
110
}
111
112
void
MenuBarPeek::hide
() {
113
m_peeking
=
false
;
114
if
(!
m_toggle
->isChecked()) {
115
m_window
->menuBar()->hide();
116
}
117
}
118
119
// Deferred: a menu's aboutToHide also fires when the pointer moves on to the
120
// next menu, and Escape is seen here before the bar leaves keyboard mode.
121
void
MenuBarPeek::hideWhenNoMenuIsOpen
() {
122
QTimer::singleShot(0,
this
, [
this
] {
123
if
(
m_peeking
&& QApplication::activePopupWidget() ==
nullptr
&&
124
m_window
->menuBar()->activeAction() ==
nullptr
) {
125
hide
();
126
}
127
});
128
}
MenuBarPeek::onKeyRelease
void onKeyRelease(const QKeyEvent *event)
Handle the release of Alt: a second lone tap hides the bar, an Alt+key chord that did not open a menu...
Definition
menubarpeek.cpp:81
MenuBarPeek::show
void show()
Show the menu bar and mark the peek as active.
Definition
menubarpeek.cpp:107
MenuBarPeek::m_peeking
bool m_peeking
true while the bar is shown because of Alt, not the toggle.
Definition
menubarpeek.h:118
MenuBarPeek::MenuBarPeek
MenuBarPeek(QMainWindow *window, QAction *toggle)
Watch window for Alt while its menu bar is hidden.
Definition
menubarpeek.cpp:17
MenuBarPeek::m_altDown
bool m_altDown
true between an Alt press in the window and its release (or the window losing activation); filters re...
Definition
menubarpeek.h:123
MenuBarPeek::m_shownByThisPress
bool m_shownByThisPress
true when the current Alt press is the one that showed the bar, so its release must not hide it again...
Definition
menubarpeek.h:133
MenuBarPeek::hideWhenNoMenuIsOpen
void hideWhenNoMenuIsOpen()
hide() on the next event-loop pass, and only if no popup is open and the bar has no active action....
Definition
menubarpeek.cpp:121
MenuBarPeek::m_window
QMainWindow * m_window
The main window whose menuBar() is shown and hidden; the parent.
Definition
menubarpeek.h:111
MenuBarPeek::eventFilter
auto eventFilter(QObject *watched, QEvent *event) -> bool override
Follows Alt, Escape, clicks and focus for the whole application.
Definition
menubarpeek.cpp:33
MenuBarPeek::onKeyPress
void onKeyPress(QObject *watched, const QKeyEvent *event)
Handle a key press seen by the application filter.
Definition
menubarpeek.cpp:61
MenuBarPeek::hide
void hide()
End the peek; hides the menu bar unless the "Show menu bar" toggle was checked in the meantime.
Definition
menubarpeek.cpp:112
MenuBarPeek::isPeeking
auto isPeeking() const -> bool
Whether the bar is up for a peek rather than by choice.
Definition
menubarpeek.cpp:31
MenuBarPeek::onMenuBar
auto onMenuBar(QObject *watched) const -> bool
Whether watched is the menu bar itself or one of its children, so a click there must not end the peek...
Definition
menubarpeek.cpp:101
MenuBarPeek::m_toggle
QAction * m_toggle
The window's "Show menu bar" action; while checked the bar is up by choice and the peek state is clea...
Definition
menubarpeek.h:116
MenuBarPeek::m_altAlone
bool m_altAlone
true while no other key has been pressed since Alt went down, i.e. the release will be a lone tap rat...
Definition
menubarpeek.h:128
MenuBarPeek::inWindow
auto inWindow(QObject *watched) const -> bool
Whether watched is a widget that belongs to the main window.
Definition
menubarpeek.cpp:96
menubarpeek.h
MenuBarPeek: shows the main window's hidden menu bar while Alt is held or tapped, and hides it again ...
src
menubarpeek.cpp
Generated by
1.18.0