File indexing completed on 2024-02-25 17:23:56

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2012 Martin Gräßlin <mgraesslin@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #pragma once
0010 #include "ui_shortcutdialog.h"
0011 
0012 #include <kwinglobals.h>
0013 
0014 // Qt
0015 #include <QDialog>
0016 #include <QObject>
0017 #include <QPointer>
0018 
0019 class QAction;
0020 class QRect;
0021 
0022 namespace KWin
0023 {
0024 class Window;
0025 
0026 /**
0027  * @brief Menu shown for a Window.
0028  *
0029  * The UserActionsMenu implements the Menu which is shown on:
0030  * @li context-menu event on Window decoration
0031  * @li window menu button
0032  * @li Keyboard Shortcut (by default Alt+F3)
0033  *
0034  * The menu contains various window management related actions for the Window the menu is opened
0035  * for, this is normally the active Window.
0036  *
0037  * The menu which is shown is tried to be as close as possible to the menu implemented in
0038  * libtaskmanager, though there are differences as there are some actions only the window manager
0039  * can provide and on the other hand the libtaskmanager cares also about things like e.g. grouping.
0040  *
0041  * Whenever the menu is changed it should be tried to also adjust the menu in libtaskmanager.
0042  *
0043  * @author Martin Gräßlin <mgraesslin@kde.org>
0044  */
0045 class KWIN_EXPORT UserActionsMenu : public QObject
0046 {
0047     Q_OBJECT
0048 public:
0049     explicit UserActionsMenu(QObject *parent = nullptr);
0050     ~UserActionsMenu() override;
0051     /**
0052      * Discards the constructed menu, so that it gets recreates
0053      * on next show event.
0054      * @see show
0055      */
0056     void discard();
0057 
0058     /**
0059      * @returns Whether the menu is currently visible
0060      */
0061     bool isShown() const;
0062 
0063     /**
0064      * grabs keyboard and mouse, workaround(?) for bug #351112
0065      */
0066     void grabInput();
0067 
0068     /**
0069      * @returns Whether the menu has a Window set to operate on.
0070      */
0071     bool hasWindow() const;
0072     /**
0073      * Checks whether the given Window @p window is the Window
0074      * for which the Menu is shown.
0075      * @param c The Window to compare
0076      * @returns Whether the Window is the one related to this Menu
0077      */
0078     bool isMenuWindow(const Window *window) const;
0079     /**
0080      * Closes the Menu and prepares it for next usage.
0081      */
0082     void close();
0083     /**
0084      * @brief Shows the menu at the given @p pos for the given @p window.
0085      *
0086      * @param pos The position where the menu should be shown.
0087      * @param window The Window for which the Menu has to be shown.
0088      */
0089     void show(const QRect &pos, Window *window);
0090 
0091 public Q_SLOTS:
0092     /**
0093      * Delayed initialization of the activity menu.
0094      *
0095      * The call to retrieve the current list of activities is performed in a thread and this
0096      * slot is invoked once the list has been fetched. Only task of this method is to decide
0097      * whether to show the activity menu and to invoke the initialization of it.
0098      *
0099      * @see initActivityPopup
0100      */
0101     void showHideActivityMenu();
0102 
0103 private Q_SLOTS:
0104     /**
0105      * The menu will become visible soon.
0106      *
0107      * Adjust the items according to the respective Window.
0108      */
0109     void menuAboutToShow();
0110 
0111     /**
0112      * The menu is about to close, all actions have been handled
0113      *
0114      * Perform cleanup
0115      */
0116     void menuAboutToHide();
0117 
0118     /**
0119      * Adjusts the desktop popup to the current values and the location of
0120      * the Window.
0121      */
0122     void desktopPopupAboutToShow();
0123     /**
0124      * Adjusts the multipleDesktopsMenu popup to the current values and the location of
0125      * the Window, Wayland only.
0126      */
0127     void multipleDesktopsPopupAboutToShow();
0128     /**
0129      * Adjusts the screen popup to the current values and the location of
0130      * the Window.
0131      */
0132     void screenPopupAboutToShow();
0133     /**
0134      * Adjusts the activity popup to the current values and the location of
0135      * the Window.
0136      */
0137     void activityPopupAboutToShow();
0138     /**
0139      * Performs a window operation.
0140      *
0141      * @param action Invoked Action containing the Window Operation to perform for the Window
0142      */
0143     void slotWindowOperation(QAction *action);
0144 
0145 private:
0146     /**
0147      * Creates the menu if not already created.
0148      */
0149     void init();
0150     /**
0151      * Creates the Move to Desktop sub-menu.
0152      */
0153     void initDesktopPopup();
0154     /**
0155      * Creates the Move to Screen sub-menu.
0156      */
0157     void initScreenPopup();
0158     /**
0159      * Creates activity popup.
0160      * I'm going with checkable ones instead of "copy to" and "move to" menus; I *think* it's an easier way.
0161      * Oh, and an 'all' option too of course
0162      */
0163     void initActivityPopup();
0164     /**
0165      * Shows a helper Dialog to inform the user how to get back in case he triggered
0166      * an action which hides the window decoration (e.g. NoBorder or Fullscreen).
0167      * @param message The message type to be shown
0168      * @param window The Window for which the dialog should be shown.
0169      */
0170     void helperDialog(const QString &message, Window *window);
0171     /**
0172      * The actual main context menu which is show when the UserActionsMenu is invoked.
0173      */
0174     QMenu *m_menu;
0175     /**
0176      * The move to desktop sub menu.
0177      */
0178     QMenu *m_desktopMenu;
0179     /**
0180      * The move to desktop sub menu, with the Wayland protocol.
0181      */
0182     QMenu *m_multipleDesktopsMenu;
0183     /**
0184      * The move to screen sub menu.
0185      */
0186     QMenu *m_screenMenu;
0187     /**
0188      * The activities sub menu.
0189      */
0190     QMenu *m_activityMenu;
0191     /**
0192      * Menu for further entries added by scripts.
0193      */
0194     QMenu *m_scriptsMenu;
0195     QAction *m_resizeOperation;
0196     QAction *m_moveOperation;
0197     QAction *m_maximizeOperation;
0198     QAction *m_shadeOperation;
0199     QAction *m_keepAboveOperation;
0200     QAction *m_keepBelowOperation;
0201     QAction *m_fullScreenOperation;
0202     QAction *m_noBorderOperation;
0203     QAction *m_minimizeOperation;
0204     QAction *m_closeOperation;
0205     QAction *m_shortcutOperation;
0206     /**
0207      * The window for which the menu is shown.
0208      */
0209     QPointer<Window> m_window;
0210     QAction *m_rulesOperation = nullptr;
0211     QAction *m_applicationRulesOperation = nullptr;
0212 };
0213 
0214 class ShortcutDialog
0215     : public QDialog
0216 {
0217     Q_OBJECT
0218 public:
0219     explicit ShortcutDialog(const QKeySequence &cut);
0220     void accept() override;
0221     QKeySequence shortcut() const;
0222 public Q_SLOTS:
0223     void keySequenceChanged();
0224 Q_SIGNALS:
0225     void dialogDone(bool ok);
0226 
0227 protected:
0228     void done(int r) override;
0229 
0230 private:
0231     Ui::ShortcutDialog m_ui;
0232     QKeySequence _shortcut;
0233 };
0234 
0235 } // namespace