Move processDecorationButton(Press|Release) to AbstractClient

This also requires to move m_decorationDoubleClickTimer and reworking
a bit how the x11 events are passed to processDecorationButtonPress.
This commit is contained in:
Martin Gräßlin 2015-12-03 16:40:27 +01:00
parent 38d3346faa
commit 5de55b61e7
5 changed files with 92 additions and 91 deletions

View file

@ -36,6 +36,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <KDecoration2/Decoration>
#include <QMouseEvent>
#include <QStyleHints>
namespace KWin
{
@ -1380,4 +1383,82 @@ void AbstractClient::processDecorationMove()
}
}
bool AbstractClient::processDecorationButtonPress(QMouseEvent *event, bool ignoreMenu)
{
Options::MouseCommand com = Options::MouseNothing;
bool active = isActive();
if (!wantsInput()) // we cannot be active, use it anyway
active = true;
// check whether it is a double click
if (event->button() == Qt::LeftButton) {
if (m_decorationDoubleClickTimer.isValid() &&
decoration()->titleBar().contains(event->x(), event->y()) &&
!m_decorationDoubleClickTimer.hasExpired(QGuiApplication::styleHints()->mouseDoubleClickInterval())) {
Workspace::self()->performWindowOperation(this, options->operationTitlebarDblClick());
dontMoveResize();
m_decorationDoubleClickTimer.invalidate();
return false;
}
m_decorationDoubleClickTimer.invalidate();
}
if (event->button() == Qt::LeftButton)
com = active ? options->commandActiveTitlebar1() : options->commandInactiveTitlebar1();
else if (event->button() == Qt::MidButton)
com = active ? options->commandActiveTitlebar2() : options->commandInactiveTitlebar2();
else if (event->button() == Qt::RightButton)
com = active ? options->commandActiveTitlebar3() : options->commandInactiveTitlebar3();
if (event->button() == Qt::LeftButton
&& com != Options::MouseOperationsMenu // actions where it's not possible to get the matching
&& com != Options::MouseMinimize // mouse release event
&& com != Options::MouseDragTab) {
setMoveResizePointerMode(mousePosition());
setMoveResizePointerButtonDown(true);
setMoveOffset(event->pos());
setInvertedMoveOffset(rect().bottomRight() - moveOffset());
setUnrestrictedMoveResize(false);
startDelayedMoveResize();
updateCursor();
}
// In the new API the decoration may process the menu action to display an inactive tab's menu.
// If the event is unhandled then the core will create one for the active window in the group.
if (!ignoreMenu || com != Options::MouseOperationsMenu)
performMouseCommand(com, event->globalPos());
return !( // Return events that should be passed to the decoration in the new API
com == Options::MouseRaise ||
com == Options::MouseOperationsMenu ||
com == Options::MouseActivateAndRaise ||
com == Options::MouseActivate ||
com == Options::MouseActivateRaiseAndPassClick ||
com == Options::MouseActivateAndPassClick ||
com == Options::MouseDragTab ||
com == Options::MouseNothing);
}
void AbstractClient::processDecorationButtonRelease(QMouseEvent *event)
{
if (isDecorated()) {
if (!event->isAccepted() && decoration()->titleBar().contains(event->pos()) && event->button() == Qt::LeftButton) {
m_decorationDoubleClickTimer.start();
}
}
if (event->buttons() == Qt::NoButton) {
setMoveResizePointerButtonDown(false);
stopDelayedMoveResize();
if (isMoveResize()) {
finishMoveResize(false);
setMoveResizePointerMode(mousePosition());
}
updateCursor();
}
}
void AbstractClient::startDecorationDoubleClickTimer()
{
m_decorationDoubleClickTimer.start();
}
}

View file

@ -27,6 +27,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <memory>
#include <QElapsedTimer>
namespace KWayland
{
namespace Server
@ -506,6 +508,8 @@ public:
void triggerDecorationRepaint();
virtual void layoutDecorationRects(QRect &left, QRect &top, QRect &right, QRect &bottom) const;
void processDecorationMove();
bool processDecorationButtonPress(QMouseEvent *event, bool ignoreMenu = false);
void processDecorationButtonRelease(QMouseEvent *event);
// TODO: remove boolean trap
static bool belongToSameApplication(const AbstractClient* c1, const AbstractClient* c2, bool active_hack = false);
@ -813,6 +817,7 @@ protected:
m_decoration = decoration;
}
virtual void destroyDecoration();
void startDecorationDoubleClickTimer();
private:
void handlePaletteChange();
@ -876,6 +881,7 @@ private:
} m_moveResize;
KDecoration2::Decoration *m_decoration = nullptr;
QElapsedTimer m_decorationDoubleClickTimer;
static bool s_haveResizeEffect;

View file

@ -2141,32 +2141,6 @@ bool Client::belongsToSameApplication(const AbstractClient *other, bool active_h
return Client::belongToSameApplication(this, c2, active_hack);
}
bool Client::processDecorationButtonPress(QMouseEvent *event)
{
return processDecorationButtonPress(qtToX11Button(event->button()), 0,
event->x(), event->y(),
event->globalX(), event->globalY());
}
void Client::processDecorationButtonRelease(QMouseEvent *event)
{
if (isDecorated()) {
if (!event->isAccepted() && decoration()->titleBar().contains(event->pos()) && event->button() == Qt::LeftButton) {
m_decorationDoubleClickTimer.start();
}
}
if (event->buttons() == Qt::NoButton) {
setMoveResizePointerButtonDown(false);
stopDelayedMoveResize();
if (isMoveResize()) {
finishMoveResize(false);
setMoveResizePointerMode(mousePosition());
}
updateCursor();
}
}
void Client::updateTabGroupStates(TabGroup::States states)
{
if (auto t = tabGroup()) {

View file

@ -162,8 +162,6 @@ public:
bool windowEvent(xcb_generic_event_t *e);
void syncEvent(xcb_sync_alarm_notify_event_t* e);
NET::WindowType windowType(bool direct = false, int supported_types = 0) const;
bool processDecorationButtonPress(QMouseEvent *event);
void processDecorationButtonRelease(QMouseEvent *event);
bool manage(xcb_window_t w, bool isMapped);
void releaseWindow(bool on_shutdown = false);
@ -401,8 +399,6 @@ private:
bool buttonReleaseEvent(xcb_window_t w, int button, int state, int x, int y, int x_root, int y_root);
bool motionNotifyEvent(xcb_window_t w, int state, int x, int y, int x_root, int y_root);
bool processDecorationButtonPress(int button, int state, int x, int y, int x_root, int y_root,
bool ignoreMenu = false);
Client* findAutogroupCandidate() const;
protected:
@ -548,7 +544,6 @@ private:
Xcb::Window m_wrapper;
Xcb::Window m_frame;
QPointer<Decoration::DecoratedClientImpl> m_decoratedClient;
QElapsedTimer m_decorationDoubleClickTimer;
QStringList activityList;
int m_activityUpdatesBlocked;
bool m_blockedActivityUpdatesRequireTransients;

View file

@ -1168,7 +1168,9 @@ bool Client::buttonPressEvent(xcb_window_t w, int button, int state, int x, int
x = x_root - geometry().x();
y = y_root - geometry().y();
// New API processes core events FIRST and only passes unused ones to the decoration
return processDecorationButtonPress(button, state, x, y, x_root, y_root, true);
QMouseEvent ev(QMouseEvent::MouseButtonPress, QPoint(x, y), QPoint(x_root, y_root),
x11ToQtMouseButton(button), x11ToQtMouseButtons(state), Qt::KeyboardModifiers());
return processDecorationButtonPress(&ev, true);
}
if (w == frameId() && isDecorated()) {
if (button >= 4 && button <= 7) {
@ -1200,7 +1202,7 @@ bool Client::buttonPressEvent(xcb_window_t w, int button, int state, int x, int
event.setAccepted(false);
QCoreApplication::sendEvent(decoration(), &event);
if (!event.isAccepted()) {
processDecorationButtonPress(button, state, x, y, x_root, y_root);
processDecorationButtonPress(&event);
}
}
return true;
@ -1208,63 +1210,6 @@ bool Client::buttonPressEvent(xcb_window_t w, int button, int state, int x, int
return true;
}
// this function processes button press events only after decoration decides not to handle them,
// unlike buttonPressEvent(), which (when the window is decoration) filters events before decoration gets them
bool Client::processDecorationButtonPress(int button, int /*state*/, int x, int y, int x_root, int y_root,
bool ignoreMenu)
{
Options::MouseCommand com = Options::MouseNothing;
bool active = isActive();
if (!wantsInput()) // we cannot be active, use it anyway
active = true;
// check whether it is a double click
if (button == XCB_BUTTON_INDEX_1) {
if (m_decorationDoubleClickTimer.isValid() &&
decoration()->titleBar().contains(x, y) &&
!m_decorationDoubleClickTimer.hasExpired(QGuiApplication::styleHints()->mouseDoubleClickInterval())) {
Workspace::self()->performWindowOperation(this, options->operationTitlebarDblClick());
dontMoveResize();
m_decorationDoubleClickTimer.invalidate();
return false;
}
m_decorationDoubleClickTimer.invalidate();
}
if (button == XCB_BUTTON_INDEX_1)
com = active ? options->commandActiveTitlebar1() : options->commandInactiveTitlebar1();
else if (button == XCB_BUTTON_INDEX_2)
com = active ? options->commandActiveTitlebar2() : options->commandInactiveTitlebar2();
else if (button == XCB_BUTTON_INDEX_3)
com = active ? options->commandActiveTitlebar3() : options->commandInactiveTitlebar3();
if (button == XCB_BUTTON_INDEX_1
&& com != Options::MouseOperationsMenu // actions where it's not possible to get the matching
&& com != Options::MouseMinimize // mouse release event
&& com != Options::MouseDragTab) {
setMoveResizePointerMode(mousePosition());
setMoveResizePointerButtonDown(true);
setMoveOffset(QPoint(x/* - padding_left*/, y/* - padding_top*/));
setInvertedMoveOffset(rect().bottomRight() - moveOffset());
setUnrestrictedMoveResize(false);
startDelayedMoveResize();
updateCursor();
}
// In the new API the decoration may process the menu action to display an inactive tab's menu.
// If the event is unhandled then the core will create one for the active window in the group.
if (!ignoreMenu || com != Options::MouseOperationsMenu)
performMouseCommand(com, QPoint(x_root, y_root));
return !( // Return events that should be passed to the decoration in the new API
com == Options::MouseRaise ||
com == Options::MouseOperationsMenu ||
com == Options::MouseActivateAndRaise ||
com == Options::MouseActivate ||
com == Options::MouseActivateRaiseAndPassClick ||
com == Options::MouseActivateAndPassClick ||
com == Options::MouseDragTab ||
com == Options::MouseNothing);
}
// return value matters only when filtering events before decoration gets them
bool Client::buttonReleaseEvent(xcb_window_t w, int button, int state, int x, int y, int x_root, int y_root)
{
@ -1280,7 +1225,7 @@ bool Client::buttonReleaseEvent(xcb_window_t w, int button, int state, int x, in
event.setAccepted(false);
QCoreApplication::sendEvent(decoration(), &event);
if (!event.isAccepted() && decoration()->titleBar().contains(x, y) && button == XCB_BUTTON_INDEX_1) {
m_decorationDoubleClickTimer.start();
startDecorationDoubleClickTimer();
}
}
}