diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4962190ddd..84797e5a60 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -184,7 +184,7 @@ qt4_add_dbus_interface( kwin_KDEINIT_SRCS
qt4_add_resources( kwin_KDEINIT_SRCS resources.qrc )
-set(kwinLibs ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${QT_QTDECLARATIVE_LIBRARY} ${KDECLARATIVE_LIBRARIES} kdecorations kwineffects ${X11_LIBRARIES} ${X11_Xrandr_LIB} ${X11_Xdamage_LIB} ${X11_Xrender_LIB} ${X11_Xfixes_LIB} ${XCB_XCB_LIBRARIES} ${X11_XCB_LIBRARIES} ${XCB_XFIXES_LIBRARIES} ${XCB_DAMAGE_LIBRARIES} ${XCB_COMPOSITE_LIBRARIES} ${XCB_SHAPE_LIBRARIES} ${XCB_SYNC_LIBRARIES} ${XCB_RENDER_LIBRARIES} ${XCB_RANDR_LIBRARIES})
+set(kwinLibs ${KDE4_KDEUI_LIBS} ${KDE4_PLASMA_LIBS} ${QT_QTDECLARATIVE_LIBRARY} ${KDECLARATIVE_LIBRARIES} kdecorations kwineffects ${X11_LIBRARIES} ${X11_Xcursor_LIB} ${X11_Xrandr_LIB} ${X11_Xdamage_LIB} ${X11_Xrender_LIB} ${X11_Xfixes_LIB} ${XCB_XCB_LIBRARIES} ${X11_XCB_LIBRARIES} ${XCB_XFIXES_LIBRARIES} ${XCB_DAMAGE_LIBRARIES} ${XCB_COMPOSITE_LIBRARIES} ${XCB_SHAPE_LIBRARIES} ${XCB_SYNC_LIBRARIES} ${XCB_RENDER_LIBRARIES} ${XCB_RANDR_LIBRARIES} ${XCB_KEYSYMS_LIBRARIES})
find_library(XF86VM_LIBRARY Xxf86vm)
if (XF86VM_LIBRARY)
diff --git a/events.cpp b/events.cpp
index 825ccfed18..c960a0ccc1 100644
--- a/events.cpp
+++ b/events.cpp
@@ -57,6 +57,7 @@ along with this program. If not, see .
#include
#include "composite.h"
+#include "killwindow.h"
namespace KWin
{
@@ -233,6 +234,12 @@ bool Workspace::workspaceEvent(XEvent * e)
&& (e->type == KeyPress || e->type == KeyRelease))
return false; // let Qt process it, it'll be intercepted again in eventFilter()
+ if (!m_windowKiller.isNull() && m_windowKiller->isActive() && m_windowKiller->isResponsibleForEvent(e->type)) {
+ m_windowKiller->processEvent(e);
+ // filter out the event
+ return true;
+ }
+
if (e->type == PropertyNotify || e->type == ClientMessage) {
unsigned long dirty[ NETRootInfo::PROPERTIES_SIZE ];
rootInfo->event(e, dirty, NETRootInfo::PROPERTIES_SIZE);
diff --git a/killwindow.cpp b/killwindow.cpp
index 57e15e525a..8aec222594 100644
--- a/killwindow.cpp
+++ b/killwindow.cpp
@@ -4,6 +4,7 @@
Copyright (C) 1999, 2000 Matthias Ettrich
Copyright (C) 2003 Lubos Lunak
+Copyright (C) 2012 Martin Gräßlin
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
@@ -18,23 +19,21 @@ 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 .
*********************************************************************/
-
-//#ifndef QT_CLEAN_NAMESPACE
-//#define QT_CLEAN_NAMESPACE
-//#endif
#include "killwindow.h"
+#include "workspace.h"
+// Qt
#include
-#include
-#include
-#include
+// XLib
#include
-#include
+#include
+// XCB
+#include
namespace KWin
{
-KillWindow::KillWindow(Workspace* ws)
- : workspace(ws)
+KillWindow::KillWindow()
+ : m_active(false)
{
}
@@ -44,71 +43,152 @@ KillWindow::~KillWindow()
void KillWindow::start()
{
- static Cursor kill_cursor = 0;
- if (!kill_cursor)
- kill_cursor = XCreateFontCursor(display(), XC_pirate);
+ static xcb_cursor_t kill_cursor = XCB_CURSOR_NONE;
+ if (kill_cursor == XCB_CURSOR_NONE) {
+ kill_cursor = createCursor();
+ }
+ if (m_active) {
+ return;
+ }
+ m_active = true;
- if (XGrabPointer(display(), rootWindow(), False,
- ButtonPressMask | ButtonReleaseMask |
- PointerMotionMask |
- EnterWindowMask | LeaveWindowMask,
- GrabModeAsync, GrabModeAsync, None,
- kill_cursor, CurrentTime) == GrabSuccess) {
- grabXKeyboard();
+ xcb_connection_t *c = connection();
+ ScopedCPointer grabPointer(xcb_grab_pointer_reply(c, xcb_grab_pointer_unchecked(c, false, rootWindow(),
+ XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE |
+ XCB_EVENT_MASK_POINTER_MOTION |
+ XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW,
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_WINDOW_NONE,
+ kill_cursor, XCB_TIME_CURRENT_TIME), NULL));
+ if (grabPointer.isNull() || grabPointer->status != XCB_GRAB_STATUS_SUCCESS) {
+ return;
+ }
+ grabXKeyboard();
+ grabXServer();
+}
- XEvent ev;
- int return_pressed = 0;
- int escape_pressed = 0;
- int button_released = 0;
+xcb_cursor_t KillWindow::createCursor()
+{
+ // XCursor is an XLib only lib
+ const char *theme = XcursorGetTheme(display());
+ const int size = XcursorGetDefaultSize(display());
+ XcursorImage *ximg = XcursorLibraryLoadImage("pirate", theme, size);
+ if (ximg) {
+ xcb_cursor_t cursor = XcursorImageLoadCursor(display(), ximg);
+ XcursorImageDestroy(ximg);
+ return cursor;
+ }
+ // fallback on font
+ xcb_connection_t *c = connection();
+ const xcb_font_t cursorFont = xcb_generate_id(c);
+ xcb_open_font(c, cursorFont, strlen ("cursor"), "cursor");
+ xcb_cursor_t cursor = xcb_generate_id(c);
+ xcb_create_glyph_cursor(c, cursor, cursorFont, cursorFont,
+ XC_pirate, /* source character glyph */
+ XC_pirate + 1, /* mask character glyph */
+ 0, 0, 0, 0, 0, 0); /* r b g r b g */
+ return cursor;
+}
- grabXServer();
-
- while (!return_pressed && !escape_pressed && !button_released) {
- XMaskEvent(display(), KeyPressMask | ButtonPressMask |
- ButtonReleaseMask | PointerMotionMask, &ev);
-
- if (ev.type == KeyPress) {
- int kc = XKeycodeToKeysym(display(), ev.xkey.keycode, 0);
- int mx = 0;
- int my = 0;
- return_pressed = (kc == XK_Return) || (kc == XK_space);
- escape_pressed = (kc == XK_Escape);
- if (kc == XK_Left) mx = -10;
- if (kc == XK_Right) mx = 10;
- if (kc == XK_Up) my = -10;
- if (kc == XK_Down) my = 10;
- if (ev.xkey.state & ControlMask) {
- mx /= 10;
- my /= 10;
- }
- QCursor::setPos(cursorPos() + QPoint(mx, my));
- }
-
- if (ev.type == ButtonRelease) {
- button_released = (ev.xbutton.button == Button1);
- if (ev.xbutton.button == Button3) {
- escape_pressed = true;
- break;
- }
- if (ev.xbutton.button == Button1 || ev.xbutton.button == Button2)
- workspace->killWindowId(ev.xbutton.subwindow);
- }
- continue;
- }
- if (return_pressed) {
- Window root, child;
- int dummy1, dummy2, dummy3, dummy4;
- unsigned int dummy5;
- if (XQueryPointer(display(), rootWindow(), &root, &child,
- &dummy1, &dummy2, &dummy3, &dummy4, &dummy5) == true
- && child != None)
- workspace->killWindowId(child);
- }
-
- ungrabXServer();
- ungrabXKeyboard();
- XUngrabPointer(display(), CurrentTime);
+bool KillWindow::isResponsibleForEvent(int eventType) const
+{
+ switch (eventType) {
+ case XCB_BUTTON_PRESS:
+ case XCB_BUTTON_RELEASE:
+ case XCB_MOTION_NOTIFY:
+ case XCB_ENTER_NOTIFY:
+ case XCB_LEAVE_NOTIFY:
+ case XCB_KEY_PRESS:
+ case XCB_KEY_RELEASE:
+ case XCB_FOCUS_IN:
+ case XCB_FOCUS_OUT:
+ return true;
+ default:
+ return false;
}
}
+void KillWindow::processEvent(XEvent *event)
+{
+ if (event->type == XCB_BUTTON_RELEASE) {
+ handleButtonRelease(event->xbutton.button, event->xbutton.subwindow);
+ } else if (event->type == XCB_KEY_PRESS) {
+ handleKeyPress(event->xkey.keycode, event->xkey.state);
+ }
+}
+
+void KillWindow::processEvent(xcb_generic_event_t *event)
+{
+ if (event->response_type == XCB_BUTTON_RELEASE) {
+ xcb_button_release_event_t *buttonEvent = reinterpret_cast(event);
+ handleButtonRelease(buttonEvent->detail, buttonEvent->child);
+ } else if (event->response_type == XCB_KEY_PRESS) {
+ xcb_key_press_event_t *keyEvent = reinterpret_cast(event);
+ handleKeyPress(keyEvent->detail, keyEvent->state);
+ }
+}
+
+void KillWindow::handleButtonRelease(xcb_button_t button, xcb_window_t window)
+{
+ if (button == XCB_BUTTON_INDEX_3) {
+ release();
+ return;
+ }
+ if (button == XCB_BUTTON_INDEX_1 || button == XCB_BUTTON_INDEX_2) {
+ Workspace::self()->killWindowId(window);
+ release();
+ return;
+ }
+}
+
+void KillWindow::handleKeyPress(xcb_keycode_t keycode, uint16_t state)
+{
+ xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(connection());
+ xcb_keysym_t kc = xcb_key_symbols_get_keysym(symbols, keycode, 0);
+ int mx = 0;
+ int my = 0;
+ const bool returnPressed = (kc == XK_Return) || (kc == XK_space);
+ const bool escapePressed = (kc == XK_Escape);
+ if (kc == XK_Left) {
+ mx = -10;
+ }
+ if (kc == XK_Right) {
+ mx = 10;
+ }
+ if (kc == XK_Up) {
+ my = -10;
+ }
+ if (kc == XK_Down) {
+ my = 10;
+ }
+ if (state & XCB_MOD_MASK_CONTROL) {
+ mx /= 10;
+ my /= 10;
+ }
+ QCursor::setPos(cursorPos() + QPoint(mx, my));
+ if (returnPressed) {
+ performKill();
+ }
+ if (returnPressed || escapePressed) {
+ release();
+ }
+ xcb_key_symbols_free(symbols);
+}
+
+void KillWindow::performKill()
+{
+ xcb_connection_t *c = connection();
+ ScopedCPointer pointer(xcb_query_pointer_reply(c, xcb_query_pointer_unchecked(c, rootWindow()), NULL));
+ if (!pointer.isNull() && pointer->child != XCB_WINDOW_NONE) {
+ Workspace::self()->killWindowId(pointer->child);
+ }
+}
+
+void KillWindow::release()
+{
+ ungrabXKeyboard();
+ xcb_ungrab_pointer(connection(), XCB_TIME_CURRENT_TIME);
+ ungrabXServer();
+ m_active = false;
+}
+
} // namespace
diff --git a/killwindow.h b/killwindow.h
index 585331ade4..0c09d84c98 100644
--- a/killwindow.h
+++ b/killwindow.h
@@ -4,6 +4,7 @@
Copyright (C) 1999, 2000 Matthias Ettrich
Copyright (C) 2003 Lubos Lunak
+Copyright (C) 2012 Martin Gräßlin
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
@@ -22,7 +23,9 @@ along with this program. If not, see .
#ifndef KWIN_KILLWINDOW_H
#define KWIN_KILLWINDOW_H
-#include "workspace.h"
+#include
+
+typedef union _XEvent XEvent;
namespace KWin
{
@@ -31,13 +34,25 @@ class KillWindow
{
public:
- KillWindow(Workspace* ws);
+ KillWindow();
~KillWindow();
void start();
+ bool isActive() const {
+ return m_active;
+ }
+ bool isResponsibleForEvent(int eventType) const;
+ // TODO: remove once event handling is ported to XCB
+ void processEvent(XEvent *event);
+ void processEvent(xcb_generic_event_t *event);
private:
- Workspace* workspace;
+ xcb_cursor_t createCursor();
+ void release();
+ void performKill();
+ void handleKeyPress(xcb_keycode_t keycode, uint16_t state);
+ void handleButtonRelease(xcb_button_t button, xcb_window_t window);
+ bool m_active;
};
} // namespace
diff --git a/useractions.cpp b/useractions.cpp
index 4824897e63..394be8f7f7 100755
--- a/useractions.cpp
+++ b/useractions.cpp
@@ -1562,8 +1562,10 @@ void Workspace::slotUntab()
*/
void Workspace::slotKillWindow()
{
- KillWindow kill(this);
- kill.start();
+ if (m_windowKiller.isNull()) {
+ m_windowKiller.reset(new KillWindow());
+ }
+ m_windowKiller->start();
}
/*!
diff --git a/workspace.h b/workspace.h
index 3c07569767..0269c0328e 100644
--- a/workspace.h
+++ b/workspace.h
@@ -42,6 +42,7 @@ along with this program. If not, see .
#include "kdecoration.h"
#include "kdecorationfactory.h"
#include "sm.h"
+#include "killwindow.h"
#include
@@ -726,6 +727,8 @@ private:
Scripting *m_scripting;
+ QScopedPointer m_windowKiller;
+
private:
friend bool performTransiencyCheck();
};