9075b5e2d6
Only delegated to Cursor::pos() anyway, so let's just use that directly. Fixes the annoyances of having to mock it in the unit tests which include utils.cpp. REVIEW: 116900
380 lines
8.7 KiB
C++
380 lines
8.7 KiB
C++
/********************************************************************
|
|
KWin - the KDE window manager
|
|
This file is part of the KDE project.
|
|
|
|
Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*********************************************************************/
|
|
|
|
#include "bridge.h"
|
|
|
|
#include "client.h"
|
|
#include "cursor.h"
|
|
#include "options.h"
|
|
|
|
#include <kconfiggroup.h>
|
|
#include "composite.h"
|
|
#include "paintredirector.h"
|
|
#include "virtualdesktops.h"
|
|
#include "workspace.h"
|
|
|
|
#include <QDebug>
|
|
|
|
namespace KWin
|
|
{
|
|
|
|
Bridge::Bridge(Client* cl)
|
|
: c(cl)
|
|
{
|
|
}
|
|
|
|
#define BRIDGE_HELPER( rettype, prototype, args1, args2, cst ) \
|
|
rettype Bridge::prototype ( args1 ) cst \
|
|
{ \
|
|
return c->prototype( args2 ); \
|
|
}
|
|
|
|
BRIDGE_HELPER(bool, isCloseable, , , const)
|
|
BRIDGE_HELPER(bool, isMaximizable, , , const)
|
|
BRIDGE_HELPER(Bridge::MaximizeMode, maximizeMode, , , const)
|
|
BRIDGE_HELPER(Bridge::QuickTileMode, quickTileMode, , , const)
|
|
BRIDGE_HELPER(bool, isMinimizable, , , const)
|
|
BRIDGE_HELPER(bool, providesContextHelp, , , const)
|
|
BRIDGE_HELPER(int, desktop, , , const)
|
|
BRIDGE_HELPER(bool, isModal, , , const)
|
|
BRIDGE_HELPER(bool, isShadeable, , , const)
|
|
BRIDGE_HELPER(bool, isShade, , , const)
|
|
BRIDGE_HELPER(bool, keepAbove, , , const)
|
|
BRIDGE_HELPER(bool, keepBelow, , , const)
|
|
BRIDGE_HELPER(bool, isMovable, , , const)
|
|
BRIDGE_HELPER(bool, isResizable, , , const)
|
|
BRIDGE_HELPER(void, processMousePressEvent, QMouseEvent* e, e,)
|
|
BRIDGE_HELPER(QRect, geometry, , , const)
|
|
BRIDGE_HELPER(void, closeWindow, , ,)
|
|
BRIDGE_HELPER(void, maximize, MaximizeMode m, m,)
|
|
BRIDGE_HELPER(void, minimize, , ,)
|
|
BRIDGE_HELPER(void, showContextHelp, , ,)
|
|
BRIDGE_HELPER(void, setDesktop, int desktop, desktop,)
|
|
BRIDGE_HELPER(QPalette, palette, , , const)
|
|
|
|
bool Bridge::isActive() const
|
|
{
|
|
return c->isActive() || (c->tabGroup() && c->tabGroup()->isActive());
|
|
}
|
|
|
|
void Bridge::setKeepAbove(bool set)
|
|
{
|
|
if (c->keepAbove() != set)
|
|
workspace()->performWindowOperation(c, KeepAboveOp);
|
|
}
|
|
|
|
void Bridge::setKeepBelow(bool set)
|
|
{
|
|
if (c->keepBelow() != set)
|
|
workspace()->performWindowOperation(c, KeepBelowOp);
|
|
}
|
|
|
|
NET::WindowType Bridge::windowType(unsigned long supported_types) const
|
|
{
|
|
return c->windowType(false, supported_types);
|
|
}
|
|
|
|
QIcon Bridge::icon() const
|
|
{
|
|
return c->icon();
|
|
}
|
|
|
|
bool Bridge::isSetShade() const
|
|
{
|
|
return c->shadeMode() != ShadeNone;
|
|
}
|
|
|
|
void Bridge::showWindowMenu(const QPoint &p)
|
|
{
|
|
workspace()->showWindowMenu(QRect(p,p), c);
|
|
}
|
|
|
|
void Bridge::showWindowMenu(const QPoint &p, long id)
|
|
{
|
|
Client *cc = clientForId(id);
|
|
if (!cc)
|
|
cc = c;
|
|
workspace()->showWindowMenu(QRect(p,p), cc);
|
|
}
|
|
|
|
void Bridge::showWindowMenu(const QRect &p)
|
|
{
|
|
workspace()->showWindowMenu(p, c);
|
|
}
|
|
|
|
void Bridge::showApplicationMenu(const QPoint &p)
|
|
{
|
|
#ifdef KWIN_BUILD_KAPPMENU
|
|
c->showApplicationMenu(p);
|
|
#else
|
|
Q_UNUSED(p)
|
|
#endif
|
|
}
|
|
|
|
bool Bridge::menuAvailable() const
|
|
{
|
|
#ifdef KWIN_BUILD_KAPPMENU
|
|
return c->menuAvailable();
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
void Bridge::performWindowOperation(WindowOperation op)
|
|
{
|
|
workspace()->performWindowOperation(c, op);
|
|
}
|
|
|
|
void Bridge::setMask(const QRegion& r, int mode)
|
|
{
|
|
c->setMask(r, mode);
|
|
}
|
|
|
|
bool Bridge::isPreview() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
QRect Bridge::iconGeometry() const
|
|
{
|
|
NETRect r = c->info->iconGeometry();
|
|
return QRect(r.pos.x, r.pos.y, r.size.width, r.size.height);
|
|
}
|
|
|
|
WId Bridge::windowId() const
|
|
{
|
|
return c->window();
|
|
}
|
|
|
|
void Bridge::titlebarDblClickOperation()
|
|
{
|
|
workspace()->performWindowOperation(c, options->operationTitlebarDblClick());
|
|
c->dontMoveResize();
|
|
}
|
|
|
|
void Bridge::titlebarMouseWheelOperation(int delta)
|
|
{
|
|
c->performMouseCommand(options->operationTitlebarMouseWheel(delta), Cursor::pos());
|
|
}
|
|
|
|
void Bridge::setShade(bool set)
|
|
{
|
|
c->setShade(set ? ShadeNormal : ShadeNone);
|
|
}
|
|
|
|
int Bridge::currentDesktop() const
|
|
{
|
|
return VirtualDesktopManager::self()->current();
|
|
}
|
|
|
|
Qt::WindowFlags Bridge::initialWFlags() const
|
|
{
|
|
return Qt::WindowDoesNotAcceptFocus;
|
|
}
|
|
|
|
QRegion Bridge::unobscuredRegion(const QRegion& r) const
|
|
{
|
|
QRegion reg(r);
|
|
const ToplevelList stacking_order = workspace()->stackingOrder();
|
|
int pos = stacking_order.indexOf(c);
|
|
++pos;
|
|
for (; pos < stacking_order.count(); ++pos) {
|
|
Client *client = qobject_cast<Client*>(stacking_order[pos]);
|
|
if (!client) {
|
|
continue;
|
|
}
|
|
if (!client->isShown(true))
|
|
continue; // these don't obscure the window
|
|
if (c->isOnAllDesktops()) {
|
|
if (!client->isOnCurrentDesktop())
|
|
continue;
|
|
} else {
|
|
if (!client->isOnDesktop(c->desktop()))
|
|
continue;
|
|
}
|
|
/* the clients all have their mask-regions in local coords
|
|
so we have to translate them to a shared coord system
|
|
we choose ours */
|
|
int dx = client->x() - c->x();
|
|
int dy = client->y() - c->y();
|
|
QRegion creg = client->mask();
|
|
creg.translate(dx, dy);
|
|
reg -= creg;
|
|
if (reg.isEmpty()) {
|
|
// early out, we are completely obscured
|
|
break;
|
|
}
|
|
}
|
|
return reg;
|
|
}
|
|
|
|
void Bridge::grabXServer(bool grab)
|
|
{
|
|
if (grab)
|
|
KWin::grabXServer();
|
|
else
|
|
KWin::ungrabXServer();
|
|
}
|
|
|
|
bool Bridge::compositingActive() const
|
|
{
|
|
return Compositor::compositing();
|
|
}
|
|
|
|
QRect Bridge::transparentRect() const
|
|
{
|
|
return c->transparentRect().translated(-c->decorationRect().topLeft());
|
|
}
|
|
|
|
void Bridge::update(const QRegion ®ion)
|
|
{
|
|
if (c->paintRedirector) {
|
|
c->paintRedirector->addRepaint(region);
|
|
}
|
|
}
|
|
|
|
//BEGIN TABBING
|
|
|
|
Client *Bridge::clientForId(long id) const
|
|
{
|
|
Client* client = reinterpret_cast<Client*>(id);
|
|
if (!workspace()->hasClient(client)) {
|
|
qWarning() << "****** ARBITRARY CODE EXECUTION ATTEMPT DETECTED ******" << id;
|
|
return 0;
|
|
}
|
|
return client;
|
|
}
|
|
|
|
int Bridge::tabCount() const
|
|
{
|
|
if (c->tabGroup())
|
|
return c->tabGroup()->count();
|
|
return 1;
|
|
}
|
|
|
|
long Bridge::tabId(int idx) const
|
|
{
|
|
if (c->tabGroup())
|
|
return tabIdOf(c->tabGroup()->clients().at(idx));
|
|
return tabIdOf(c);
|
|
}
|
|
|
|
QIcon Bridge::icon(int idx) const
|
|
{
|
|
if (c->tabGroup()) {
|
|
return c->tabGroup()->clients().at(idx)->icon();
|
|
}
|
|
return icon();
|
|
}
|
|
|
|
QString Bridge::caption() const
|
|
{
|
|
return c->caption(true, true);
|
|
}
|
|
|
|
QString Bridge::caption(int idx) const
|
|
{
|
|
if (c->tabGroup())
|
|
return c->tabGroup()->clients().at(idx)->caption(true, true);
|
|
return c->caption(true, true);
|
|
}
|
|
|
|
long Bridge::currentTabId() const
|
|
{
|
|
if (c->tabGroup())
|
|
return tabIdOf(c->tabGroup()->current());
|
|
return 0;
|
|
}
|
|
|
|
void Bridge::setCurrentTab(long id)
|
|
{
|
|
if (c->tabGroup())
|
|
c->tabGroup()->setCurrent(clientForId(id));
|
|
}
|
|
|
|
void Bridge::tab_A_before_B(long A, long B)
|
|
{
|
|
if (!B) {
|
|
if (c->tabGroup()) {
|
|
if (Client *a = clientForId(A))
|
|
a->untab();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (Client *a = clientForId(A))
|
|
if (Client *b = clientForId(B))
|
|
if (a != b)
|
|
a->tabBefore(b, true);
|
|
}
|
|
|
|
void Bridge::tab_A_behind_B(long A, long B)
|
|
{
|
|
if (!B) {
|
|
if (c->tabGroup()) {
|
|
if (Client *a = clientForId(A))
|
|
a->untab();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (Client *a = clientForId(A))
|
|
if (Client *b = clientForId(B))
|
|
if (a != b)
|
|
a->tabBehind(b, true);
|
|
}
|
|
|
|
|
|
void Bridge::untab(long id, const QRect& newGeom)
|
|
{
|
|
if (c->tabGroup())
|
|
if (Client* client = clientForId(id))
|
|
if (client->untab(newGeom)) {
|
|
if (options->focusPolicyIsReasonable())
|
|
workspace()->takeActivity(client, Workspace::ActivityFocus | Workspace::ActivityRaise);
|
|
workspace()->raiseClient(client);
|
|
}
|
|
}
|
|
|
|
void Bridge::closeTab(long id)
|
|
{
|
|
if (Client* client = clientForId(id))
|
|
client->closeWindow();
|
|
}
|
|
|
|
void Bridge::closeTabGroup()
|
|
{
|
|
if (c->tabGroup())
|
|
c->tabGroup()->closeAll();
|
|
}
|
|
|
|
//END TABBING
|
|
|
|
bool Bridge::isOnAllDesktopsAvailable() const
|
|
{
|
|
return VirtualDesktopManager::self()->count() > 1;
|
|
}
|
|
|
|
KDecoration::WindowOperation Bridge::buttonToWindowOperation(Qt::MouseButtons button)
|
|
{
|
|
return c->mouseButtonToWindowOperation(button);
|
|
}
|
|
|
|
} // namespace
|