Change the way how effects can get mouse events
With the removal of BoxSwitch all effects which want mouse events use the fullscreen input window. The available functionality is too complex both in EffectsHandler and in the Effects. With this change only fullscreen input windows are supported and all effects share the input window. This means there is at maximum one input window. This simplifies the code in the Effects as they don't have to keep track of the window they created any more. In EffectsHandler it means that only one window needs to be created, destroyed and raised. Also it means that we can properly react on screen size changes which had been ignored in the past. Also quite some roundtrips to X are no longer needed as we do not need to query the window geometry when creating the input window. REVIEW: 110156
This commit is contained in:
parent
0811d17329
commit
49e734f743
15 changed files with 166 additions and 213 deletions
224
effects.cpp
224
effects.cpp
|
@ -270,9 +270,6 @@ EffectsHandlerImpl::~EffectsHandlerImpl()
|
|||
ungrabKeyboard();
|
||||
foreach (const EffectPair & ep, loaded_effects)
|
||||
unloadEffect(ep.first);
|
||||
foreach (const InputWindowPair & pos, input_windows) {
|
||||
xcb_destroy_window(connection(), pos.second);
|
||||
}
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::setupClientConnections(Client* c)
|
||||
|
@ -689,6 +686,50 @@ void EffectsHandlerImpl::grabbedKeyboardEvent(QKeyEvent* e)
|
|||
keyboard_grab_effect->grabbedKeyboardEvent(e);
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::startMouseInterception(Effect *effect, Qt::CursorShape shape)
|
||||
{
|
||||
if (m_grabbedMouseEffects.contains(effect)) {
|
||||
return;
|
||||
}
|
||||
m_grabbedMouseEffects.append(effect);
|
||||
if (m_grabbedMouseEffects.size() != 1) {
|
||||
return;
|
||||
}
|
||||
// NOTE: it is intended to not perform an XPointerGrab on X11. See documentation in kwineffects.h
|
||||
// The mouse grab is implemented by using a full screen input only window
|
||||
if (!m_mouseInterceptionWindow.isValid()) {
|
||||
const QRect geo(0, 0, displayWidth(), displayHeight());
|
||||
const uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
|
||||
const uint32_t values[] = {
|
||||
true,
|
||||
XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION,
|
||||
Cursor::x11Cursor(shape)
|
||||
};
|
||||
m_mouseInterceptionWindow.reset(Xcb::createInputWindow(geo, mask, values));
|
||||
}
|
||||
m_mouseInterceptionWindow.map();
|
||||
m_mouseInterceptionWindow.raise();
|
||||
// Raise electric border windows above the input windows
|
||||
// so they can still be triggered.
|
||||
#ifdef KWIN_BUILD_SCREENEDGES
|
||||
ScreenEdges::self()->ensureOnTop();
|
||||
#endif
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::stopMouseInterception(Effect *effect)
|
||||
{
|
||||
if (!m_grabbedMouseEffects.contains(effect)) {
|
||||
return;
|
||||
}
|
||||
m_grabbedMouseEffects.removeAll(effect);
|
||||
if (m_grabbedMouseEffects.isEmpty()) {
|
||||
m_mouseInterceptionWindow.unmap();
|
||||
#ifdef KWIN_BUILD_SCREENEDGES
|
||||
Workspace::self()->stackScreenEdgesUnderOverrideRedirect();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void* EffectsHandlerImpl::getProxy(QString name)
|
||||
{
|
||||
// All effects start with "kwin4_effect_", prepend it to the name
|
||||
|
@ -719,6 +760,9 @@ bool EffectsHandlerImpl::hasKeyboardGrab() const
|
|||
void EffectsHandlerImpl::desktopResized(const QSize &size)
|
||||
{
|
||||
m_scene->screenGeometryChanged(size);
|
||||
if (m_mouseInterceptionWindow.isValid()) {
|
||||
m_mouseInterceptionWindow.setGeometry(QRect(0, 0, size.width(), size.height()));
|
||||
}
|
||||
emit screenGeometryChanged(size);
|
||||
}
|
||||
|
||||
|
@ -1130,158 +1174,65 @@ QRect EffectsHandlerImpl::clientArea(clientAreaOption opt, const QPoint& p, int
|
|||
return Workspace::self()->clientArea(opt, p, desktop);
|
||||
}
|
||||
|
||||
xcb_window_t EffectsHandlerImpl::createInputWindow(Effect* e, int x, int y, int w, int h, const QCursor& cursor)
|
||||
void EffectsHandlerImpl::defineCursor(Qt::CursorShape shape)
|
||||
{
|
||||
xcb_window_t win = XCB_WINDOW_NONE;
|
||||
QList<InputWindowPair>::iterator it = input_windows.begin();
|
||||
while (it != input_windows.end()) {
|
||||
if (it->first != e) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
Xcb::WindowAttributes attributes(it->second);
|
||||
Xcb::WindowGeometry geometry(it->second);
|
||||
if (!attributes) {
|
||||
// this is some random junk that certainly should no be here
|
||||
kDebug(1212) << "found input window that is NOT on the server, something is VERY broken here";
|
||||
Q_ASSERT(false); // exit in debug mode - for releases we'll be a bit more graceful
|
||||
it = input_windows.erase(it);
|
||||
continue;
|
||||
}
|
||||
if (geometry.rect() == QRect(x, y, w, h)) {
|
||||
win = it->second; // re-use
|
||||
break;
|
||||
} else if (attributes->map_state == XCB_MAP_STATE_UNMAPPED) {
|
||||
// probably old one, likely no longer of interest
|
||||
xcb_destroy_window(connection(), it->second);
|
||||
it = input_windows.erase(it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
if (!m_mouseInterceptionWindow.isValid()) {
|
||||
return;
|
||||
}
|
||||
if (win == XCB_WINDOW_NONE) {
|
||||
win = xcb_generate_id(connection());
|
||||
// TODO keeping on top?
|
||||
// TODO enter/leave notify?
|
||||
const uint32_t mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK | XCB_CW_CURSOR;
|
||||
const uint32_t values[] = {
|
||||
true,
|
||||
XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION,
|
||||
Cursor::x11Cursor(cursor.shape())
|
||||
};
|
||||
xcb_create_window(connection(), 0, win, rootWindow(), x, y, w, h, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
|
||||
XCB_COPY_FROM_PARENT, mask, values);
|
||||
input_windows.append(qMakePair(e, win));
|
||||
}
|
||||
xcb_map_window(connection(), win);
|
||||
const uint32_t values[] = { XCB_STACK_MODE_ABOVE };
|
||||
xcb_configure_window(connection(), win, XCB_CONFIG_WINDOW_STACK_MODE, values);
|
||||
// Raise electric border windows above the input windows
|
||||
// so they can still be triggered.
|
||||
#ifdef KWIN_BUILD_SCREENEDGES
|
||||
ScreenEdges::self()->ensureOnTop();
|
||||
#endif
|
||||
if (input_windows.count() > 10) // that sounds like some leak - could still be correct, thoug - so NO ABORT HERE!
|
||||
kDebug() << "** warning ** there are now " << input_windows.count() <<
|
||||
"input windows what's a bit much - please have a look and if this counts up, better report a bug";
|
||||
return win;
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::destroyInputWindow(xcb_window_t w)
|
||||
{
|
||||
foreach (const InputWindowPair & pos, input_windows) {
|
||||
if (pos.second == w) {
|
||||
xcb_unmap_window(connection(), w);
|
||||
#ifdef KWIN_BUILD_SCREENEDGES
|
||||
Workspace::self()->stackScreenEdgesUnderOverrideRedirect();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
abort();
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::defineCursor(xcb_window_t w, Qt::CursorShape shape)
|
||||
{
|
||||
Xcb::defineCursor(w, Cursor::x11Cursor(shape));
|
||||
m_mouseInterceptionWindow.defineCursor(Cursor::x11Cursor(shape));
|
||||
}
|
||||
|
||||
bool EffectsHandlerImpl::checkInputWindowEvent(XEvent* e)
|
||||
{
|
||||
if (e->type != ButtonPress && e->type != ButtonRelease && e->type != MotionNotify)
|
||||
return false;
|
||||
foreach (const InputWindowPair & pos, input_windows) {
|
||||
if (pos.second == e->xany.window) {
|
||||
switch(e->type) {
|
||||
case ButtonPress: {
|
||||
XButtonEvent* e2 = &e->xbutton;
|
||||
Qt::MouseButton button = x11ToQtMouseButton(e2->button);
|
||||
Qt::MouseButtons buttons = x11ToQtMouseButtons(e2->state) | button;
|
||||
QMouseEvent ev(QEvent::MouseButtonPress,
|
||||
QPoint(e2->x, e2->y), QPoint(e2->x_root, e2->y_root),
|
||||
button, buttons, x11ToQtKeyboardModifiers(e2->state));
|
||||
pos.first->windowInputMouseEvent(pos.second, &ev);
|
||||
break; // --->
|
||||
}
|
||||
case ButtonRelease: {
|
||||
XButtonEvent* e2 = &e->xbutton;
|
||||
Qt::MouseButton button = x11ToQtMouseButton(e2->button);
|
||||
Qt::MouseButtons buttons = x11ToQtMouseButtons(e2->state) & ~button;
|
||||
QMouseEvent ev(QEvent::MouseButtonRelease,
|
||||
QPoint(e2->x, e2->y), QPoint(e2->x_root, e2->y_root),
|
||||
button, buttons, x11ToQtKeyboardModifiers(e2->state));
|
||||
pos.first->windowInputMouseEvent(pos.second, &ev);
|
||||
break; // --->
|
||||
}
|
||||
case MotionNotify: {
|
||||
XMotionEvent* e2 = &e->xmotion;
|
||||
QMouseEvent ev(QEvent::MouseMove, QPoint(e2->x, e2->y), QPoint(e2->x_root, e2->y_root),
|
||||
Qt::NoButton, x11ToQtMouseButtons(e2->state), x11ToQtKeyboardModifiers(e2->state));
|
||||
pos.first->windowInputMouseEvent(pos.second, &ev);
|
||||
break; // --->
|
||||
}
|
||||
}
|
||||
return true; // eat event
|
||||
if (m_grabbedMouseEffects.isEmpty() || m_mouseInterceptionWindow != e->xany.window) {
|
||||
return false;
|
||||
}
|
||||
foreach (Effect *effect, m_grabbedMouseEffects) {
|
||||
switch(e->type) {
|
||||
case ButtonPress: {
|
||||
XButtonEvent* e2 = &e->xbutton;
|
||||
Qt::MouseButton button = x11ToQtMouseButton(e2->button);
|
||||
Qt::MouseButtons buttons = x11ToQtMouseButtons(e2->state) | button;
|
||||
QMouseEvent ev(QEvent::MouseButtonPress,
|
||||
QPoint(e2->x, e2->y), QPoint(e2->x_root, e2->y_root),
|
||||
button, buttons, x11ToQtKeyboardModifiers(e2->state));
|
||||
effect->windowInputMouseEvent(&ev);
|
||||
break; // --->
|
||||
}
|
||||
case ButtonRelease: {
|
||||
XButtonEvent* e2 = &e->xbutton;
|
||||
Qt::MouseButton button = x11ToQtMouseButton(e2->button);
|
||||
Qt::MouseButtons buttons = x11ToQtMouseButtons(e2->state) & ~button;
|
||||
QMouseEvent ev(QEvent::MouseButtonRelease,
|
||||
QPoint(e2->x, e2->y), QPoint(e2->x_root, e2->y_root),
|
||||
button, buttons, x11ToQtKeyboardModifiers(e2->state));
|
||||
effect->windowInputMouseEvent(&ev);
|
||||
break; // --->
|
||||
}
|
||||
case MotionNotify: {
|
||||
XMotionEvent* e2 = &e->xmotion;
|
||||
QMouseEvent ev(QEvent::MouseMove, QPoint(e2->x, e2->y), QPoint(e2->x_root, e2->y_root),
|
||||
Qt::NoButton, x11ToQtMouseButtons(e2->state), x11ToQtKeyboardModifiers(e2->state));
|
||||
effect->windowInputMouseEvent(&ev);
|
||||
break; // --->
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return true; // eat event
|
||||
}
|
||||
|
||||
void EffectsHandlerImpl::checkInputWindowStacking()
|
||||
{
|
||||
if (input_windows.count() == 0)
|
||||
if (m_grabbedMouseEffects.isEmpty()) {
|
||||
return;
|
||||
xcb_window_t* wins = new xcb_window_t[input_windows.count()];
|
||||
QVector<Xcb::WindowAttributes> attributes(input_windows.count());
|
||||
int pos = 0;
|
||||
foreach (const InputWindowPair &it, input_windows) {
|
||||
attributes[pos] = Xcb::WindowAttributes(it.second);
|
||||
pos++;
|
||||
}
|
||||
pos = 0;
|
||||
for (QVector<Xcb::WindowAttributes>::iterator it = attributes.begin(); it != attributes.end(); ++it) {
|
||||
if (*it && (*it)->map_state != XCB_MAP_STATE_UNMAPPED) {
|
||||
wins[pos++] = (*it).window();
|
||||
}
|
||||
}
|
||||
if (pos) {
|
||||
const uint32_t values[] = { XCB_STACK_MODE_ABOVE };
|
||||
xcb_configure_window(connection(), wins[0], XCB_CONFIG_WINDOW_STACK_MODE, values);
|
||||
for (int i=1; i<pos; ++i) {
|
||||
const uint16_t mask = XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE;
|
||||
const uint32_t stackingValues[] = {
|
||||
wins[i-1],
|
||||
XCB_STACK_MODE_BELOW
|
||||
};
|
||||
xcb_configure_window(connection(), wins[i], mask, stackingValues);
|
||||
}
|
||||
}
|
||||
delete[] wins;
|
||||
m_mouseInterceptionWindow.raise();
|
||||
// Raise electric border windows above the input windows
|
||||
// so they can still be triggered. TODO: Do both at once.
|
||||
#ifdef KWIN_BUILD_SCREENEDGES
|
||||
if (pos)
|
||||
ScreenEdges::self()->ensureOnTop();
|
||||
ScreenEdges::self()->ensureOnTop();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1521,6 +1472,7 @@ void EffectsHandlerImpl::unloadEffect(const QString& name)
|
|||
if (activeFullScreenEffect() == it.value().second) {
|
||||
setActiveFullScreenEffect(0);
|
||||
}
|
||||
stopMouseInterception(it.value().second);
|
||||
// remove support properties for the effect
|
||||
const QList<QByteArray> properties = m_propertiesForEffects.keys();
|
||||
foreach (const QByteArray &property, properties) {
|
||||
|
|
13
effects.h
13
effects.h
|
@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "kwineffects.h"
|
||||
|
||||
#include "scene.h"
|
||||
#include "xcbutils.h"
|
||||
|
||||
#include <QStack>
|
||||
#include <QHash>
|
||||
|
@ -38,7 +39,6 @@ class OrgFreedesktopScreenSaverInterface;
|
|||
|
||||
namespace KWin
|
||||
{
|
||||
typedef QPair< Effect*, xcb_window_t > InputWindowPair;
|
||||
|
||||
class AbstractThumbnailItem;
|
||||
class DesktopThumbnailItem;
|
||||
|
@ -110,6 +110,9 @@ public:
|
|||
virtual QPoint cursorPos() const;
|
||||
virtual bool grabKeyboard(Effect* effect);
|
||||
virtual void ungrabKeyboard();
|
||||
// not performing XGrabPointer
|
||||
virtual void startMouseInterception(Effect *effect, Qt::CursorShape shape);
|
||||
virtual void stopMouseInterception(Effect *effect);
|
||||
virtual void* getProxy(QString name);
|
||||
virtual void startMousePolling();
|
||||
virtual void stopMousePolling();
|
||||
|
@ -143,10 +146,7 @@ public:
|
|||
virtual double animationTimeFactor() const;
|
||||
virtual WindowQuadType newWindowQuadType();
|
||||
|
||||
virtual xcb_window_t createInputWindow(Effect* e, int x, int y, int w, int h, const QCursor& cursor);
|
||||
using EffectsHandler::createInputWindow;
|
||||
virtual void destroyInputWindow(xcb_window_t w);
|
||||
virtual void defineCursor(xcb_window_t w, Qt::CursorShape shape);
|
||||
virtual void defineCursor(Qt::CursorShape shape);
|
||||
virtual bool checkInputWindowEvent(XEvent* e);
|
||||
virtual void checkInputWindowStacking();
|
||||
|
||||
|
@ -262,10 +262,11 @@ private:
|
|||
QHash<QByteArray, qulonglong> m_managedProperties;
|
||||
Compositor *m_compositor;
|
||||
Scene *m_scene;
|
||||
QList< InputWindowPair > input_windows;
|
||||
ScreenLockerWatcher *m_screenLockerWatcher;
|
||||
bool m_desktopRendering;
|
||||
int m_currentRenderedDesktop;
|
||||
Xcb::Window m_mouseInterceptionWindow;
|
||||
QList<Effect*> m_grabbedMouseEffects;
|
||||
};
|
||||
|
||||
class EffectWindowImpl : public EffectWindow
|
||||
|
|
|
@ -527,7 +527,7 @@ void CoverSwitchEffect::slotTabBoxAdded(int mode)
|
|||
(mode == TabBoxCurrentAppWindowsMode && primaryTabBox) ||
|
||||
(mode == TabBoxCurrentAppWindowsAlternativeMode && secondaryTabBox))
|
||||
&& effects->currentTabBoxWindowList().count() > 0) {
|
||||
input = effects->createFullScreenInputWindow(this, Qt::ArrowCursor);
|
||||
effects->startMouseInterception(this, Qt::ArrowCursor);
|
||||
activeScreen = effects->activeScreen();
|
||||
if (!stop && !stopRequested) {
|
||||
effects->refTabBox();
|
||||
|
@ -598,7 +598,7 @@ void CoverSwitchEffect::slotTabBoxClosed()
|
|||
effects->setActiveFullScreenEffect(0);
|
||||
mActivated = false;
|
||||
effects->unrefTabBox();
|
||||
effects->destroyInputWindow(input);
|
||||
effects->stopMouseInterception(this);
|
||||
effects->addRepaintFull();
|
||||
}
|
||||
}
|
||||
|
@ -891,10 +891,8 @@ void CoverSwitchEffect::paintWindows(const EffectWindowList& windows, bool left,
|
|||
}
|
||||
}
|
||||
|
||||
void CoverSwitchEffect::windowInputMouseEvent(Window w, QEvent* e)
|
||||
void CoverSwitchEffect::windowInputMouseEvent(QEvent* e)
|
||||
{
|
||||
assert(w == input);
|
||||
Q_UNUSED(w);
|
||||
if (e->type() != QEvent::MouseButtonPress)
|
||||
return;
|
||||
// we don't want click events during animations
|
||||
|
@ -965,7 +963,7 @@ void CoverSwitchEffect::abort()
|
|||
// in this case the cleanup is already done (see bug 207554)
|
||||
if (mActivated) {
|
||||
effects->unrefTabBox();
|
||||
effects->destroyInputWindow(input);
|
||||
effects->stopMouseInterception(this);
|
||||
}
|
||||
effects->setActiveFullScreenEffect(0);
|
||||
mActivated = false;
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
virtual void paintScreen(int mask, QRegion region, ScreenPaintData& data);
|
||||
virtual void postPaintScreen();
|
||||
virtual void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data);
|
||||
virtual void windowInputMouseEvent(Window w, QEvent* e);
|
||||
virtual void windowInputMouseEvent(QEvent* e);
|
||||
virtual bool isActive() const;
|
||||
|
||||
static bool supported();
|
||||
|
@ -131,7 +131,6 @@ private:
|
|||
bool startRequested;
|
||||
QTimeLine timeLine;
|
||||
QRect area;
|
||||
Window input;
|
||||
float zPosition;
|
||||
float scaleFactor;
|
||||
enum Direction {
|
||||
|
|
|
@ -1136,7 +1136,7 @@ void CubeEffect::postPaintScreen()
|
|||
if (keyboard_grab)
|
||||
effects->ungrabKeyboard();
|
||||
keyboard_grab = false;
|
||||
effects->destroyInputWindow(input);
|
||||
effects->stopMouseInterception(this);
|
||||
|
||||
effects->setActiveFullScreenEffect(0);
|
||||
|
||||
|
@ -1896,8 +1896,7 @@ void CubeEffect::setActive(bool active)
|
|||
activated = true;
|
||||
activeScreen = effects->activeScreen();
|
||||
keyboard_grab = effects->grabKeyboard(this);
|
||||
input = effects->createInputWindow(this, 0, 0, displayWidth(), displayHeight(),
|
||||
Qt::OpenHandCursor);
|
||||
effects->startMouseInterception(this, Qt::OpenHandCursor);
|
||||
frontDesktop = effects->currentDesktop();
|
||||
zoom = 0.0;
|
||||
zOrderingFactor = zPosition / (effects->stackingOrder().count() - 1);
|
||||
|
@ -1983,10 +1982,10 @@ void CubeEffect::slotMouseChanged(const QPoint& pos, const QPoint& oldpos, Qt::M
|
|||
}
|
||||
}
|
||||
if (!oldbuttons.testFlag(Qt::LeftButton) && buttons.testFlag(Qt::LeftButton)) {
|
||||
effects->defineCursor(input, Qt::ClosedHandCursor);
|
||||
effects->defineCursor(Qt::ClosedHandCursor);
|
||||
}
|
||||
if (oldbuttons.testFlag(Qt::LeftButton) && !buttons.testFlag(Qt::LeftButton)) {
|
||||
effects->defineCursor(input, Qt::OpenHandCursor);
|
||||
effects->defineCursor(Qt::OpenHandCursor);
|
||||
if (closeOnMouseRelease)
|
||||
setActive(false);
|
||||
}
|
||||
|
@ -1996,10 +1995,8 @@ void CubeEffect::slotMouseChanged(const QPoint& pos, const QPoint& oldpos, Qt::M
|
|||
}
|
||||
}
|
||||
|
||||
void CubeEffect::windowInputMouseEvent(Window w, QEvent* e)
|
||||
void CubeEffect::windowInputMouseEvent(QEvent* e)
|
||||
{
|
||||
assert(w == input);
|
||||
Q_UNUSED(w);
|
||||
QMouseEvent *mouse = dynamic_cast< QMouseEvent* >(e);
|
||||
if (mouse && mouse->type() == QEvent::MouseButtonRelease) {
|
||||
if (mouse->button() == Qt::XButton1) {
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
virtual void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data);
|
||||
virtual bool borderActivated(ElectricBorder border);
|
||||
virtual void grabbedKeyboardEvent(QKeyEvent* e);
|
||||
virtual void windowInputMouseEvent(Window w, QEvent* e);
|
||||
virtual void windowInputMouseEvent(QEvent* e);
|
||||
virtual bool isActive() const;
|
||||
|
||||
// proxy functions
|
||||
|
@ -179,7 +179,6 @@ private:
|
|||
QList<ElectricBorder> borderActivateCylinder;
|
||||
QList<ElectricBorder> borderActivateSphere;
|
||||
int painting_desktop;
|
||||
Window input;
|
||||
int frontDesktop;
|
||||
float cubeOpacity;
|
||||
bool opacityDesktopOnly;
|
||||
|
|
|
@ -462,7 +462,7 @@ void DesktopGridEffect::slotWindowGeometryShapeChanged(EffectWindow* w, const QR
|
|||
}
|
||||
}
|
||||
|
||||
void DesktopGridEffect::windowInputMouseEvent(Window, QEvent* e)
|
||||
void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
|
||||
{
|
||||
if ((e->type() != QEvent::MouseMove
|
||||
&& e->type() != QEvent::MouseButtonPress
|
||||
|
@ -521,7 +521,7 @@ void DesktopGridEffect::windowInputMouseEvent(Window, QEvent* e)
|
|||
}
|
||||
m_proxy->calculateWindowTransformations(manager.managedWindows(), windowMove->screen(), manager);
|
||||
}
|
||||
effects->defineCursor(input, Qt::ClosedHandCursor);
|
||||
effects->defineCursor(Qt::ClosedHandCursor);
|
||||
}
|
||||
wasWindowMove = true;
|
||||
if (windowMove->isMovable() && !isUsingPresentWindows()) {
|
||||
|
@ -539,7 +539,7 @@ void DesktopGridEffect::windowInputMouseEvent(Window, QEvent* e)
|
|||
} else if ((me->buttons() & Qt::LeftButton) && !wasDesktopMove &&
|
||||
(me->pos() - dragStartPos).manhattanLength() > KGlobalSettings::dndEventDelay()) {
|
||||
wasDesktopMove = true;
|
||||
effects->defineCursor(input, Qt::ClosedHandCursor);
|
||||
effects->defineCursor(Qt::ClosedHandCursor);
|
||||
}
|
||||
if (d != highlightedDesktop) { // Highlight desktop
|
||||
if ((me->buttons() & Qt::LeftButton) && isValidMove && !wasWindowMove && d <= effects->numberOfDesktops()) {
|
||||
|
@ -673,9 +673,9 @@ void DesktopGridEffect::windowInputMouseEvent(Window, QEvent* e)
|
|||
}
|
||||
effects->setElevatedWindow(windowMove, false);
|
||||
windowMove = NULL;
|
||||
effects->defineCursor(input, Qt::PointingHandCursor);
|
||||
effects->defineCursor(Qt::PointingHandCursor);
|
||||
} else if (wasDesktopMove)
|
||||
effects->defineCursor(input, Qt::PointingHandCursor);
|
||||
effects->defineCursor(Qt::PointingHandCursor);
|
||||
wasWindowMove = false;
|
||||
wasDesktopMove = false;
|
||||
}
|
||||
|
@ -1061,8 +1061,7 @@ void DesktopGridEffect::setActive(bool active)
|
|||
void DesktopGridEffect::setup()
|
||||
{
|
||||
keyboardGrab = effects->grabKeyboard(this);
|
||||
input = effects->createInputWindow(this, 0, 0, displayWidth(), displayHeight(),
|
||||
Qt::PointingHandCursor);
|
||||
effects->startMouseInterception(this, Qt::PointingHandCursor);
|
||||
effects->setActiveFullScreenEffect(this);
|
||||
setHighlightedDesktop(effects->currentDesktop());
|
||||
|
||||
|
@ -1193,7 +1192,7 @@ void DesktopGridEffect::finish()
|
|||
if (keyboardGrab)
|
||||
effects->ungrabKeyboard();
|
||||
keyboardGrab = false;
|
||||
effects->destroyInputWindow(input);
|
||||
effects->stopMouseInterception(this);
|
||||
effects->setActiveFullScreenEffect(0);
|
||||
if (isUsingPresentWindows()) {
|
||||
while (!m_managers.isEmpty()) {
|
||||
|
|
|
@ -66,7 +66,7 @@ public:
|
|||
virtual void postPaintScreen();
|
||||
virtual void prePaintWindow(EffectWindow* w, WindowPrePaintData& data, int time);
|
||||
virtual void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data);
|
||||
virtual void windowInputMouseEvent(Window w, QEvent* e);
|
||||
virtual void windowInputMouseEvent(QEvent* e);
|
||||
virtual void grabbedKeyboardEvent(QKeyEvent* e);
|
||||
virtual bool borderActivated(ElectricBorder border);
|
||||
virtual bool isActive() const;
|
||||
|
@ -139,7 +139,6 @@ private:
|
|||
int paintingDesktop;
|
||||
int highlightedDesktop;
|
||||
int m_originalMovingDesktop;
|
||||
Window input;
|
||||
bool keyboardGrab;
|
||||
bool wasWindowMove, wasDesktopMove, isValidMove;
|
||||
EffectWindow* windowMove;
|
||||
|
|
|
@ -614,16 +614,16 @@ void FlipSwitchEffect::setActive(bool activate, FlipSwitchMode mode)
|
|||
switch(m_mode) {
|
||||
case TabboxMode:
|
||||
m_selectedWindow = effects->currentTabBoxWindow();
|
||||
m_input = effects->createFullScreenInputWindow(this, Qt::ArrowCursor);
|
||||
effects->startMouseInterception(this, Qt::ArrowCursor);
|
||||
break;
|
||||
case CurrentDesktopMode:
|
||||
m_selectedWindow = effects->activeWindow();
|
||||
m_input = effects->createFullScreenInputWindow(this, Qt::BlankCursor);
|
||||
effects->startMouseInterception(this, Qt::BlankCursor);
|
||||
m_hasKeyboardGrab = effects->grabKeyboard(this);
|
||||
break;
|
||||
case AllDesktopsMode:
|
||||
m_selectedWindow = effects->activeWindow();
|
||||
m_input = effects->createFullScreenInputWindow(this, Qt::BlankCursor);
|
||||
effects->startMouseInterception(this, Qt::BlankCursor);
|
||||
m_hasKeyboardGrab = effects->grabKeyboard(this);
|
||||
break;
|
||||
}
|
||||
|
@ -661,7 +661,7 @@ void FlipSwitchEffect::setActive(bool activate, FlipSwitchMode mode)
|
|||
}
|
||||
} else
|
||||
m_startStopTimeLine.setCurveShape(QTimeLine::EaseInOutCurve);
|
||||
effects->destroyInputWindow(m_input);
|
||||
effects->stopMouseInterception(this);
|
||||
if (m_hasKeyboardGrab) {
|
||||
effects->ungrabKeyboard();
|
||||
m_hasKeyboardGrab = false;
|
||||
|
@ -962,10 +962,8 @@ void FlipSwitchEffect::updateCaption()
|
|||
// Mouse handling
|
||||
//*************************************************************
|
||||
|
||||
void FlipSwitchEffect::windowInputMouseEvent(Window w, QEvent* e)
|
||||
void FlipSwitchEffect::windowInputMouseEvent(QEvent* e)
|
||||
{
|
||||
assert(w == m_input);
|
||||
Q_UNUSED(w);
|
||||
if (e->type() != QEvent::MouseButtonPress)
|
||||
return;
|
||||
// we don't want click events during animations
|
||||
|
|
|
@ -53,7 +53,7 @@ public:
|
|||
virtual void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, int time);
|
||||
virtual void paintWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data);
|
||||
virtual void grabbedKeyboardEvent(QKeyEvent* e);
|
||||
virtual void windowInputMouseEvent(Window w, QEvent* e);
|
||||
virtual void windowInputMouseEvent(QEvent* e);
|
||||
virtual bool isActive() const;
|
||||
|
||||
static bool supported();
|
||||
|
@ -128,7 +128,6 @@ private:
|
|||
bool m_stop;
|
||||
bool m_animation;
|
||||
bool m_hasKeyboardGrab;
|
||||
Window m_input;
|
||||
FlipSwitchMode m_mode;
|
||||
EffectFrame* m_captionFrame;
|
||||
QFont m_captionFont;
|
||||
|
|
|
@ -514,11 +514,8 @@ bool PresentWindowsEffect::borderActivated(ElectricBorder border)
|
|||
return true;
|
||||
}
|
||||
|
||||
void PresentWindowsEffect::windowInputMouseEvent(Window w, QEvent *e)
|
||||
void PresentWindowsEffect::windowInputMouseEvent(QEvent *e)
|
||||
{
|
||||
assert(w == m_input);
|
||||
Q_UNUSED(w);
|
||||
|
||||
QMouseEvent* me = static_cast< QMouseEvent* >(e);
|
||||
if (m_closeView && m_closeView->geometry().contains(me->pos())) {
|
||||
if (!m_closeView->isVisible()) {
|
||||
|
@ -574,7 +571,7 @@ void PresentWindowsEffect::windowInputMouseEvent(Window w, QEvent *e)
|
|||
m_highlightedDropTarget = NULL;
|
||||
}
|
||||
effects->addRepaintFull();
|
||||
effects->defineCursor(m_input, Qt::PointingHandCursor);
|
||||
effects->defineCursor(Qt::PointingHandCursor);
|
||||
return;
|
||||
}
|
||||
if (hovering) {
|
||||
|
@ -613,7 +610,7 @@ void PresentWindowsEffect::windowInputMouseEvent(Window w, QEvent *e)
|
|||
m_highlightedDropTarget->setIcon(icon.pixmap(QSize(128, 128), QIcon::Normal));
|
||||
m_highlightedDropTarget = NULL;
|
||||
}
|
||||
effects->defineCursor(m_input, Qt::PointingHandCursor);
|
||||
effects->defineCursor(Qt::PointingHandCursor);
|
||||
} else if (e->type() == QEvent::MouseButtonPress && me->button() == Qt::LeftButton && hovering && m_dragToClose) {
|
||||
m_dragStart = me->pos();
|
||||
m_dragWindow = m_highlightedWindow;
|
||||
|
@ -625,7 +622,7 @@ void PresentWindowsEffect::windowInputMouseEvent(Window w, QEvent *e)
|
|||
if (e->type() == QEvent::MouseMove && m_dragWindow) {
|
||||
if ((me->pos() - m_dragStart).manhattanLength() > KGlobalSettings::dndEventDelay() && !m_dragInProgress) {
|
||||
m_dragInProgress = true;
|
||||
effects->defineCursor(m_input, Qt::ForbiddenCursor);
|
||||
effects->defineCursor(Qt::ForbiddenCursor);
|
||||
}
|
||||
if (!m_dragInProgress) {
|
||||
return;
|
||||
|
@ -643,13 +640,13 @@ void PresentWindowsEffect::windowInputMouseEvent(Window w, QEvent *e)
|
|||
KIcon icon("user-trash");
|
||||
effects->addRepaint(m_highlightedDropTarget->geometry());
|
||||
m_highlightedDropTarget->setIcon(icon.pixmap(QSize(128, 128), QIcon::Active));
|
||||
effects->defineCursor(m_input, Qt::DragMoveCursor);
|
||||
effects->defineCursor(Qt::DragMoveCursor);
|
||||
} else if (!target && m_highlightedDropTarget) {
|
||||
KIcon icon("user-trash");
|
||||
effects->addRepaint(m_highlightedDropTarget->geometry());
|
||||
m_highlightedDropTarget->setIcon(icon.pixmap(QSize(128, 128), QIcon::Normal));
|
||||
m_highlightedDropTarget = NULL;
|
||||
effects->defineCursor(m_input, Qt::ForbiddenCursor);
|
||||
effects->defineCursor(Qt::ForbiddenCursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1533,7 +1530,7 @@ void PresentWindowsEffect::setActive(bool active)
|
|||
}
|
||||
|
||||
// Create temporary input window to catch mouse events
|
||||
m_input = effects->createFullScreenInputWindow(this, Qt::PointingHandCursor);
|
||||
effects->startMouseInterception(this, Qt::PointingHandCursor);
|
||||
m_hasKeyboardGrab = effects->grabKeyboard(this);
|
||||
effects->setActiveFullScreenEffect(this);
|
||||
|
||||
|
@ -1576,7 +1573,7 @@ void PresentWindowsEffect::setActive(bool active)
|
|||
m_windowFilter.clear();
|
||||
m_selectedWindows.clear();
|
||||
|
||||
effects->destroyInputWindow(m_input);
|
||||
effects->stopMouseInterception(this);
|
||||
if (m_hasKeyboardGrab)
|
||||
effects->ungrabKeyboard();
|
||||
m_hasKeyboardGrab = false;
|
||||
|
|
|
@ -109,7 +109,7 @@ public:
|
|||
|
||||
// User interaction
|
||||
virtual bool borderActivated(ElectricBorder border);
|
||||
virtual void windowInputMouseEvent(Window w, QEvent *e);
|
||||
virtual void windowInputMouseEvent(QEvent *e);
|
||||
virtual void grabbedKeyboardEvent(QKeyEvent *e);
|
||||
virtual bool isActive() const;
|
||||
|
||||
|
@ -275,7 +275,6 @@ private:
|
|||
bool m_activated;
|
||||
bool m_ignoreMinimized;
|
||||
double m_decalOpacity;
|
||||
Window m_input;
|
||||
bool m_hasKeyboardGrab;
|
||||
PresentWindowsMode m_mode;
|
||||
int m_desktop;
|
||||
|
|
|
@ -469,7 +469,7 @@ void* Effect::proxy()
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void Effect::windowInputMouseEvent(Window, QEvent*)
|
||||
void Effect::windowInputMouseEvent(QEvent*)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -603,16 +603,6 @@ EffectsHandler::~EffectsHandler()
|
|||
assert(loaded_effects.count() == 0);
|
||||
}
|
||||
|
||||
xcb_window_t EffectsHandler::createInputWindow(Effect* e, const QRect& r, const QCursor& cursor)
|
||||
{
|
||||
return createInputWindow(e, r.x(), r.y(), r.width(), r.height(), cursor);
|
||||
}
|
||||
|
||||
xcb_window_t EffectsHandler::createFullScreenInputWindow(Effect* e, const QCursor& cursor)
|
||||
{
|
||||
return createInputWindow(e, 0, 0, displayWidth(), displayHeight(), cursor);
|
||||
}
|
||||
|
||||
CompositingType EffectsHandler::compositingType() const
|
||||
{
|
||||
return compositing_type;
|
||||
|
|
|
@ -170,7 +170,7 @@ X-KDE-Library=kwin4_effect_cooleffect
|
|||
|
||||
#define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor ))
|
||||
#define KWIN_EFFECT_API_VERSION_MAJOR 0
|
||||
#define KWIN_EFFECT_API_VERSION_MINOR 222
|
||||
#define KWIN_EFFECT_API_VERSION_MINOR 223
|
||||
#define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \
|
||||
KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR )
|
||||
|
||||
|
@ -434,7 +434,7 @@ public:
|
|||
**/
|
||||
virtual void buildQuads(EffectWindow* w, WindowQuadList& quadList);
|
||||
|
||||
virtual void windowInputMouseEvent(Window w, QEvent* e);
|
||||
virtual void windowInputMouseEvent(QEvent* e);
|
||||
virtual void grabbedKeyboardEvent(QKeyEvent* e);
|
||||
|
||||
/**
|
||||
|
@ -644,17 +644,35 @@ public:
|
|||
virtual void drawWindow(EffectWindow* w, int mask, QRegion region, WindowPaintData& data) = 0;
|
||||
virtual void buildQuads(EffectWindow* w, WindowQuadList& quadList) = 0;
|
||||
virtual QVariant kwinOption(KWinOption kwopt) = 0;
|
||||
// Functions for handling input - e.g. when an Expose-like effect is shown, an input window
|
||||
// covering the whole screen is created and all mouse events will be intercepted by it.
|
||||
// The effect's windowInputMouseEvent() will get called with such events.
|
||||
virtual xcb_window_t createInputWindow(Effect* e, int x, int y, int w, int h, const QCursor& cursor) = 0;
|
||||
xcb_window_t createInputWindow(Effect* e, const QRect& r, const QCursor& cursor);
|
||||
virtual xcb_window_t createFullScreenInputWindow(Effect* e, const QCursor& cursor);
|
||||
virtual void destroyInputWindow(xcb_window_t w) = 0;
|
||||
virtual void defineCursor(xcb_window_t w, Qt::CursorShape shape) = 0;
|
||||
/**
|
||||
* Sets the cursor while the mouse is intercepted.
|
||||
* @see startMouseInterception
|
||||
* @since 4.11
|
||||
**/
|
||||
virtual void defineCursor(Qt::CursorShape shape) = 0;
|
||||
virtual QPoint cursorPos() const = 0;
|
||||
virtual bool grabKeyboard(Effect* effect) = 0;
|
||||
virtual void ungrabKeyboard() = 0;
|
||||
/**
|
||||
* Ensures that all mouse events are sent to the @p effect.
|
||||
* No window will get the mouse events. Only fullscreen effects providing a custom user interface should
|
||||
* be using this method. The input events are delivered to Effect::windowInputMouseEvent.
|
||||
*
|
||||
* NOTE: this method does not perform an X11 mouse grab. On X11 a fullscreen input window is raised above
|
||||
* all other windows, but no grab is performed.
|
||||
*
|
||||
* @param shape Sets the cursor to be used while the mouse is intercepted
|
||||
* @see stopMouseInterception
|
||||
* @see Effect::windowInputMouseEvent
|
||||
* @since 4.11
|
||||
**/
|
||||
virtual void startMouseInterception(Effect *effect, Qt::CursorShape shape) = 0;
|
||||
/**
|
||||
* Releases the hold mouse interception for @p effect
|
||||
* @see startMouseInterception
|
||||
* @since 4.11
|
||||
**/
|
||||
virtual void stopMouseInterception(Effect *effect) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the proxy class for an effect if it has one. Will return NULL if
|
||||
|
|
|
@ -348,6 +348,7 @@ public:
|
|||
void move(uint32_t x, uint32_t y);
|
||||
void resize(const QSize &size);
|
||||
void resize(uint32_t width, uint32_t height);
|
||||
void raise();
|
||||
void map();
|
||||
void unmap();
|
||||
/**
|
||||
|
@ -492,6 +493,13 @@ void Window::resize(uint32_t width, uint32_t height)
|
|||
xcb_configure_window(connection(), m_window, mask, values);
|
||||
}
|
||||
|
||||
inline
|
||||
void Window::raise()
|
||||
{
|
||||
const uint32_t values[] = { XCB_STACK_MODE_ABOVE };
|
||||
xcb_configure_window(connection(), m_window, XCB_CONFIG_WINDOW_STACK_MODE, values);
|
||||
}
|
||||
|
||||
inline
|
||||
void Window::map()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue