QMenuPrivate: Make sloppyDelayTimer non-static
[qt:qt.git] / src / gui / widgets / qmenu_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QMENU_P_H
43 #define QMENU_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists purely as an
50 // implementation detail.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55
56 #include "QtGui/qmenubar.h"
57 #include "QtGui/qstyleoption.h"
58 #include "QtCore/qdatetime.h"
59 #include "QtCore/qmap.h"
60 #include "QtCore/qhash.h"
61 #include "QtCore/qbasictimer.h"
62 #include "private/qwidget_p.h"
63
64 #ifdef Q_WS_S60
65 class CEikMenuPane;
66 #define QT_SYMBIAN_FIRST_MENU_ITEM 32000
67 #define QT_SYMBIAN_LAST_MENU_ITEM 41999 // 10000 items ought to be enough for anybody...
68 #endif
69 QT_BEGIN_NAMESPACE
70
71 #ifndef QT_NO_MENU
72
73 #ifdef Q_WS_S60
74 void qt_symbian_next_menu_from_action(QWidget* actionContainer);
75 void qt_symbian_show_toplevel(CEikMenuPane* menuPane);
76 void qt_symbian_show_submenu(CEikMenuPane* menuPane, int id);
77 #endif // Q_WS_S60
78
79 class QTornOffMenu;
80 class QEventLoop;
81
82 #ifdef Q_WS_MAC
83 #  ifdef __OBJC__
84 QT_END_NAMESPACE
85 @class NSMenuItem;
86 QT_BEGIN_NAMESPACE
87 #  else
88 typedef void NSMenuItem;
89 #  endif //__OBJC__
90 struct QMacMenuAction {
91     QMacMenuAction()
92 #ifndef QT_MAC_USE_COCOA
93        : command(0)
94 #else
95        : menuItem(0)
96 #endif
97          , ignore_accel(0), merged(0), menu(0)
98     {
99     }
100     ~QMacMenuAction();
101 #ifndef QT_MAC_USE_COCOA
102     uint command;
103 #else
104     NSMenuItem *menuItem;
105 #endif
106     uchar ignore_accel : 1;
107     uchar merged : 1;
108     QPointer<QAction> action;
109     OSMenuRef menu;
110 };
111
112 struct QMenuMergeItem
113 {
114 #ifndef QT_MAC_USE_COCOA
115     inline QMenuMergeItem(MenuCommand c, QMacMenuAction *a) : command(c), action(a) { }
116     MenuCommand command;
117 #else
118     inline QMenuMergeItem(NSMenuItem *c, QMacMenuAction *a) : menuItem(c), action(a) { }
119     NSMenuItem *menuItem;
120 #endif
121     QMacMenuAction *action;
122 };
123 typedef QList<QMenuMergeItem> QMenuMergeList;
124 #endif
125
126 #ifdef Q_WS_WINCE
127 struct QWceMenuAction {
128     uint command;
129     QPointer<QAction> action;
130     HMENU menuHandle;
131     QWceMenuAction() : menuHandle(0), command(0) {}
132 };
133 #endif
134 #ifdef Q_WS_S60
135 struct QSymbianMenuAction {
136     uint command;
137     int parent;
138     CEikMenuPane* menuPane;
139     QPointer<QAction> action;
140     QSymbianMenuAction() : command(0) {}
141 };
142 #endif
143
144 class QMenuPrivate : public QWidgetPrivate
145 {
146     Q_DECLARE_PUBLIC(QMenu)
147 public:
148     QMenuPrivate() : itemsDirty(0), maxIconWidth(0), tabWidth(0), ncols(0),
149                       collapsibleSeparators(true), activationRecursionGuard(false), hasHadMouse(0), aboutToHide(0), motions(0),
150                       currentAction(0),
151 #ifdef QT_KEYPAD_NAVIGATION
152                       selectAction(0),
153                       cancelAction(0),
154 #endif
155                       scroll(0), eventLoop(0), tearoff(0), tornoff(0), tearoffHighlighted(0),
156                       hasCheckableItems(0), sloppyDelayTimer(0), sloppyAction(0), doChildEffects(false)
157 #ifdef QT3_SUPPORT
158                       ,emitHighlighted(false)
159 #endif
160 #ifdef Q_WS_MAC
161                       ,mac_menu(0)
162 #endif
163 #if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
164                       ,wce_menu(0)
165 #endif
166 #ifdef Q_WS_S60
167                       ,symbian_menu(0)
168 #endif
169     { }
170     ~QMenuPrivate()
171     {
172         delete scroll;
173 #ifdef Q_WS_MAC
174         delete mac_menu;
175 #endif
176 #if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
177         delete wce_menu;
178 #endif
179 #ifdef Q_WS_S60
180         delete symbian_menu;
181 #endif
182
183     }
184     void init();
185
186     static QMenuPrivate *get(QMenu *m) { return m->d_func(); }
187     int scrollerHeight() const;
188
189     //item calculations
190     mutable uint itemsDirty : 1;
191     mutable uint maxIconWidth, tabWidth;
192     QRect actionRect(QAction *) const;
193
194     mutable QVector<QRect> actionRects;
195     mutable QHash<QAction *, QWidget *> widgetItems;
196     void updateActionRects() const;
197     void updateActionRects(const QRect &screen) const;
198     QRect popupGeometry(const QWidget *widget) const;
199     QRect popupGeometry(int screen = -1) const;
200     mutable uint ncols : 4; //4 bits is probably plenty
201     uint collapsibleSeparators : 1;
202     QSize adjustMenuSizeForScreen(const QRect & screen);
203     int getLastVisibleAction() const;
204
205     bool activationRecursionGuard;
206
207     //selection
208     static QMenu *mouseDown;
209     QPoint mousePopupPos;
210     uint hasHadMouse : 1;
211     uint aboutToHide : 1;
212     int motions;
213     QAction *currentAction;
214 #ifdef QT_KEYPAD_NAVIGATION
215     QAction *selectAction;
216     QAction *cancelAction;
217 #endif
218     QBasicTimer menuDelayTimer;
219     enum SelectionReason {
220         SelectedFromKeyboard,
221         SelectedFromElsewhere
222     };
223     QWidget *topCausedWidget() const;
224     QAction *actionAt(QPoint p) const;
225     void setFirstActionActive();
226     void setCurrentAction(QAction *, int popup = -1, SelectionReason reason = SelectedFromElsewhere, bool activateFirst = false);
227     void popupAction(QAction *, int, bool);
228     void setSyncAction();
229
230     //scrolling support
231     struct QMenuScroller {
232         enum ScrollLocation { ScrollStay, ScrollBottom, ScrollTop, ScrollCenter };
233         enum ScrollDirection { ScrollNone=0, ScrollUp=0x01, ScrollDown=0x02 };
234         uint scrollFlags : 2, scrollDirection : 2;
235         int scrollOffset;
236         QBasicTimer scrollTimer;
237
238         QMenuScroller() : scrollFlags(ScrollNone), scrollDirection(ScrollNone), scrollOffset(0) { }
239         ~QMenuScroller() { }
240     } *scroll;
241     void scrollMenu(QMenuScroller::ScrollLocation location, bool active=false);
242     void scrollMenu(QMenuScroller::ScrollDirection direction, bool page=false, bool active=false);
243     void scrollMenu(QAction *action, QMenuScroller::ScrollLocation location, bool active=false);
244
245     //synchronous operation (ie exec())
246     QEventLoop *eventLoop;
247     QPointer<QAction> syncAction;
248
249     //search buffer
250     QString searchBuffer;
251     QBasicTimer searchBufferTimer;
252
253     //passing of mouse events up the parent hierarchy
254     QPointer<QMenu> activeMenu;
255     bool mouseEventTaken(QMouseEvent *);
256
257     //used to walk up the popup list
258     struct QMenuCaused {
259         QPointer<QWidget> widget;
260         QPointer<QAction> action;
261     };
262     virtual QList<QPointer<QWidget> > calcCausedStack() const;
263     QMenuCaused causedPopup;
264     void hideUpToMenuBar();
265     void hideMenu(QMenu *menu, bool justRegister = false);
266
267     //index mappings
268     inline QAction *actionAt(int i) const { return q_func()->actions().at(i); }
269     inline int indexOf(QAction *act) const { return q_func()->actions().indexOf(act); }
270
271     //tear off support
272     uint tearoff : 1, tornoff : 1, tearoffHighlighted : 1;
273     QPointer<QTornOffMenu> tornPopup;
274
275     mutable bool hasCheckableItems;
276
277     //sloppy selection
278     int sloppyDelayTimer;
279     mutable QAction *sloppyAction;
280     QRegion sloppyRegion;
281
282     //default action
283     QPointer<QAction> defaultAction;
284
285     QAction *menuAction;
286     QAction *defaultMenuAction;
287
288     void setOverrideMenuAction(QAction *);
289     void _q_overrideMenuActionDestroyed();
290
291     //firing of events
292     void activateAction(QAction *, QAction::ActionEvent, bool self=true);
293     void activateCausedStack(const QList<QPointer<QWidget> > &, QAction *, QAction::ActionEvent, bool);
294
295     void _q_actionTriggered();
296     void _q_actionHovered();
297
298     bool hasMouseMoved(const QPoint &globalPos);
299
300     void updateLayoutDirection();
301
302     //menu fading/scrolling effects
303     bool doChildEffects;
304
305 #ifdef Q_WS_MAC
306     //mac menu binding
307     struct QMacMenuPrivate {
308         QList<QMacMenuAction*> actionItems;
309         OSMenuRef menu;
310         QMacMenuPrivate();
311         ~QMacMenuPrivate();
312
313         bool merged(const QAction *action) const;
314         void addAction(QAction *, QMacMenuAction* =0, QMenuPrivate *qmenu = 0);
315         void addAction(QMacMenuAction *, QMacMenuAction* =0, QMenuPrivate *qmenu = 0);
316         void syncAction(QMacMenuAction *);
317         inline void syncAction(QAction *a) { syncAction(findAction(a)); }
318         void removeAction(QMacMenuAction *);
319         inline void removeAction(QAction *a) { removeAction(findAction(a)); }
320         inline QMacMenuAction *findAction(QAction *a) {
321             for(int i = 0; i < actionItems.size(); i++) {
322                 QMacMenuAction *act = actionItems[i];
323                 if(a == act->action)
324                     return act;
325             }
326             return 0;
327         }
328     } *mac_menu;
329     OSMenuRef macMenu(OSMenuRef merge);
330 #ifndef QT_MAC_USE_COCOA
331     void setMacMenuEnabled(bool enable = true);
332 #endif
333     void syncSeparatorsCollapsible(bool collapsible);
334     static QHash<OSMenuRef, OSMenuRef> mergeMenuHash;
335     static QHash<OSMenuRef, QMenuMergeList*> mergeMenuItemsHash;
336 #endif
337
338     QPointer<QAction> actionAboutToTrigger;
339 #ifdef QT3_SUPPORT
340     bool emitHighlighted;
341 #endif
342
343 #if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
344     struct QWceMenuPrivate {
345         QList<QWceMenuAction*> actionItems;
346         HMENU menuHandle;
347         QWceMenuPrivate();
348         ~QWceMenuPrivate();
349         void addAction(QAction *, QWceMenuAction* =0);
350         void addAction(QWceMenuAction *, QWceMenuAction* =0);
351         void syncAction(QWceMenuAction *);
352         inline void syncAction(QAction *a) { syncAction(findAction(a)); }
353         void removeAction(QWceMenuAction *);
354         void rebuild();
355         inline void removeAction(QAction *a) { removeAction(findAction(a)); }
356         inline QWceMenuAction *findAction(QAction *a) {
357             for(int i = 0; i < actionItems.size(); i++) {
358                 QWceMenuAction *act = actionItems[i];
359                 if(a == act->action)
360                     return act;
361             }
362             return 0;
363         }
364     } *wce_menu;
365     HMENU wceMenu();
366     QAction* wceCommands(uint command);
367 #endif
368 #if defined(Q_WS_S60)
369     struct QSymbianMenuPrivate {
370         QList<QSymbianMenuAction*> actionItems;
371         QSymbianMenuPrivate();
372         ~QSymbianMenuPrivate();
373         void addAction(QAction *, QSymbianMenuAction* =0);
374         void addAction(QSymbianMenuAction *, QSymbianMenuAction* =0);
375         void syncAction(QSymbianMenuAction *);
376         inline void syncAction(QAction *a) { syncAction(findAction(a)); }
377         void removeAction(QSymbianMenuAction *);
378         void rebuild(bool reCreate = false);
379         inline void removeAction(QAction *a) { removeAction(findAction(a)); }
380         inline QSymbianMenuAction *findAction(QAction *a) {
381             for(int i = 0; i < actionItems.size(); i++) {
382                 QSymbianMenuAction *act = actionItems[i];
383                 if(a == act->action)
384                     return act;
385             }
386             return 0;
387         }
388     } *symbian_menu;
389 #endif
390     QPointer<QWidget> noReplayFor;
391 };
392
393 #endif // QT_NO_MENU
394
395 QT_END_NAMESPACE
396
397 #endif // QMENU_P_H