Changeset View
Changeset View
Standalone View
Standalone View
x11locker.cpp
Show First 20 Lines • Show All 45 Lines • ▼ Show 20 Line(s) | |||||
46 | static Atom gXA_SCREENSAVER_VERSION; | 46 | static Atom gXA_SCREENSAVER_VERSION; | ||
47 | 47 | | |||
48 | namespace ScreenLocker | 48 | namespace ScreenLocker | ||
49 | { | 49 | { | ||
50 | 50 | | |||
51 | X11Locker::X11Locker(QObject *parent) | 51 | X11Locker::X11Locker(QObject *parent) | ||
52 | : AbstractLocker(parent) | 52 | : AbstractLocker(parent) | ||
53 | , QAbstractNativeEventFilter() | 53 | , QAbstractNativeEventFilter() | ||
54 | , m_focusedLockWindow(XCB_WINDOW_NONE) | ||||
54 | { | 55 | { | ||
55 | initialize(); | 56 | initialize(); | ||
56 | } | 57 | } | ||
57 | 58 | | |||
58 | X11Locker::~X11Locker() | 59 | X11Locker::~X11Locker() | ||
59 | { | 60 | { | ||
60 | qApp->removeNativeEventFilter(this); | 61 | qApp->removeNativeEventFilter(this); | ||
61 | } | 62 | } | ||
▲ Show 20 Lines • Show All 162 Lines • ▼ Show 20 Line(s) | |||||
224 | // | 225 | // | ||
225 | // Remove the virtual root property | 226 | // Remove the virtual root property | ||
226 | // | 227 | // | ||
227 | void X11Locker::removeVRoot(Window win) | 228 | void X11Locker::removeVRoot(Window win) | ||
228 | { | 229 | { | ||
229 | XDeleteProperty (QX11Info::display(), win, gXA_VROOT); | 230 | XDeleteProperty (QX11Info::display(), win, gXA_VROOT); | ||
230 | } | 231 | } | ||
231 | 232 | | |||
232 | static void fakeFocusIn( WId window ) | 233 | void X11Locker::fakeFocusIn( WId window ) | ||
233 | { | 234 | { | ||
235 | if (window == m_focusedLockWindow) { | ||||
236 | return; | ||||
237 | } | ||||
238 | | ||||
234 | // We have keyboard grab, so this application will | 239 | // We have keyboard grab, so this application will | ||
235 | // get keyboard events even without having focus. | 240 | // get keyboard events even without having focus. | ||
236 | // Fake FocusIn to make Qt realize it has the active | 241 | // Fake FocusIn to make Qt realize it has the active | ||
237 | // window, so that it will correctly show cursor in the dialog. | 242 | // window, so that it will correctly show cursor in the dialog. | ||
238 | XEvent ev; | 243 | XEvent ev; | ||
239 | memset(&ev, 0, sizeof(ev)); | 244 | memset(&ev, 0, sizeof(ev)); | ||
240 | ev.xfocus.display = QX11Info::display(); | 245 | ev.xfocus.display = QX11Info::display(); | ||
241 | ev.xfocus.type = FocusIn; | 246 | ev.xfocus.type = FocusIn; | ||
242 | ev.xfocus.window = window; | 247 | ev.xfocus.window = window; | ||
243 | ev.xfocus.mode = NotifyNormal; | 248 | ev.xfocus.mode = NotifyNormal; | ||
244 | ev.xfocus.detail = NotifyAncestor; | 249 | ev.xfocus.detail = NotifyAncestor; | ||
245 | XSendEvent( QX11Info::display(), window, False, NoEventMask, &ev ); | 250 | XSendEvent( QX11Info::display(), window, False, NoEventMask, &ev ); | ||
246 | XFlush(QX11Info::display()); | 251 | XFlush(QX11Info::display()); | ||
252 | | ||||
253 | m_focusedLockWindow = window; | ||||
247 | } | 254 | } | ||
248 | 255 | | |||
249 | template< typename T> | 256 | template< typename T> | ||
250 | void coordFromEvent(xcb_generic_event_t *event, int *x, int *y) | 257 | void coordFromEvent(xcb_generic_event_t *event, int *x, int *y) | ||
251 | { | 258 | { | ||
252 | T *e = reinterpret_cast<T*>(event); | 259 | T *e = reinterpret_cast<T*>(event); | ||
253 | *x = e->event_x; | 260 | *x = e->event_x; | ||
254 | *y = e->event_y; | 261 | *y = e->event_y; | ||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Line(s) | 309 | foreach (WId window, m_lockWindows) { | |||
303 | if (XGetGeometry(QX11Info::display(), window, &root_return, | 310 | if (XGetGeometry(QX11Info::display(), window, &root_return, | ||
304 | &x_return, &y_return, | 311 | &x_return, &y_return, | ||
305 | &width_return, &height_return, | 312 | &width_return, &height_return, | ||
306 | &border_width_return, &depth_return) | 313 | &border_width_return, &depth_return) | ||
307 | && | 314 | && | ||
308 | (x>=x_return && x<=x_return+(int)width_return) | 315 | (x>=x_return && x<=x_return+(int)width_return) | ||
309 | && | 316 | && | ||
310 | (y>=y_return && y<=y_return+(int)height_return) ) { | 317 | (y>=y_return && y<=y_return+(int)height_return) ) { | ||
318 | // We need to do our own focus handling (see comment in fakeFocusIn). | ||||
319 | // For now: Focus on clicks inside the window | ||||
320 | if (responseType == XCB_BUTTON_PRESS) { | ||||
321 | fakeFocusIn(window); | ||||
322 | } | ||||
311 | const int targetX = x - x_return; | 323 | const int targetX = x - x_return; | ||
312 | const int targetY = y - y_return; | 324 | const int targetY = y - y_return; | ||
313 | if (responseType == XCB_KEY_PRESS || responseType == XCB_KEY_RELEASE) { | 325 | if (responseType == XCB_KEY_PRESS || responseType == XCB_KEY_RELEASE) { | ||
314 | sendEvent<xcb_key_press_event_t>(event, window, targetX, targetY); | 326 | sendEvent<xcb_key_press_event_t>(event, window, targetX, targetY); | ||
315 | } else if (responseType == XCB_BUTTON_PRESS || responseType == XCB_BUTTON_RELEASE) { | 327 | } else if (responseType == XCB_BUTTON_PRESS || responseType == XCB_BUTTON_RELEASE) { | ||
316 | sendEvent<xcb_button_press_event_t>(event, window, targetX, targetY); | 328 | sendEvent<xcb_button_press_event_t>(event, window, targetX, targetY); | ||
317 | } else if (responseType == XCB_MOTION_NOTIFY) { | 329 | } else if (responseType == XCB_MOTION_NOTIFY) { | ||
318 | sendEvent<xcb_motion_notify_event_t>(event, window, targetX, targetY); | 330 | sendEvent<xcb_motion_notify_event_t>(event, window, targetX, targetY); | ||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Line(s) | 391 | case XCB_UNMAP_NOTIFY: { | |||
381 | if (xu->event == QX11Info::appRootWindow()) { | 393 | if (xu->event == QX11Info::appRootWindow()) { | ||
382 | qDebug() << "UnmapNotify:" << xu->window; | 394 | qDebug() << "UnmapNotify:" << xu->window; | ||
383 | int index = findWindowInfo( xu->window ); | 395 | int index = findWindowInfo( xu->window ); | ||
384 | if( index >= 0 ) | 396 | if( index >= 0 ) | ||
385 | m_windowInfo[ index ].viewable = false; | 397 | m_windowInfo[ index ].viewable = false; | ||
386 | else | 398 | else | ||
387 | qDebug() << "Unknown toplevel for MapNotify"; | 399 | qDebug() << "Unknown toplevel for MapNotify"; | ||
388 | m_lockWindows.removeAll(xu->event); | 400 | m_lockWindows.removeAll(xu->event); | ||
401 | if (m_focusedLockWindow == xu->event && !m_lockWindows.empty()) { | ||||
402 | // The currently focused window vanished, just focus the first one in the list | ||||
403 | fakeFocusIn(m_lockWindows[0]); | ||||
404 | } | ||||
389 | ret = true; | 405 | ret = true; | ||
390 | } | 406 | } | ||
391 | break; | 407 | break; | ||
392 | } | 408 | } | ||
393 | case XCB_CREATE_NOTIFY: { | 409 | case XCB_CREATE_NOTIFY: { | ||
394 | xcb_create_notify_event_t *xc = reinterpret_cast<xcb_create_notify_event_t*>(event); | 410 | xcb_create_notify_event_t *xc = reinterpret_cast<xcb_create_notify_event_t*>(event); | ||
395 | if (xc->parent == QX11Info::appRootWindow()) { | 411 | if (xc->parent == QX11Info::appRootWindow()) { | ||
396 | qDebug() << "CreateNotify:" << xc->window; | 412 | qDebug() << "CreateNotify:" << xc->window; | ||
▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Line(s) | 513 | { | |||
503 | } | 519 | } | ||
504 | if (m_lockWindows.contains(window)) { | 520 | if (m_lockWindows.contains(window)) { | ||
505 | qDebug() << "uhoh! duplicate!"; | 521 | qDebug() << "uhoh! duplicate!"; | ||
506 | } else { | 522 | } else { | ||
507 | if (!m_background->isVisible()) { | 523 | if (!m_background->isVisible()) { | ||
508 | // not yet shown and we have a lock window, so we show our own window | 524 | // not yet shown and we have a lock window, so we show our own window | ||
509 | m_background->show(); | 525 | m_background->show(); | ||
510 | } | 526 | } | ||
511 | m_lockWindows.prepend(window); | 527 | | ||
528 | if (m_lockWindows.empty()) { | ||||
529 | // Make sure to focus the first window | ||||
530 | m_focusedLockWindow = XCB_WINDOW_NONE; | ||||
512 | fakeFocusIn(window); | 531 | fakeFocusIn(window); | ||
532 | } | ||||
533 | | ||||
534 | m_lockWindows.prepend(window); | ||||
513 | stayOnTop(); | 535 | stayOnTop(); | ||
514 | } | 536 | } | ||
515 | } | 537 | } | ||
516 | 538 | | |||
517 | } | 539 | } |