Changeset View
Changeset View
Standalone View
Standalone View
events.cpp
Show All 19 Lines | |||||
20 | *********************************************************************/ | 20 | *********************************************************************/ | ||
21 | 21 | | |||
22 | /* | 22 | /* | ||
23 | 23 | | |||
24 | This file contains things relevant to handling incoming events. | 24 | This file contains things relevant to handling incoming events. | ||
25 | 25 | | |||
26 | */ | 26 | */ | ||
27 | 27 | | |||
28 | #include "client.h" | 28 | #include "x11client.h" | ||
29 | #include "cursor.h" | 29 | #include "cursor.h" | ||
30 | #include "focuschain.h" | 30 | #include "focuschain.h" | ||
31 | #include "netinfo.h" | 31 | #include "netinfo.h" | ||
32 | #include "workspace.h" | 32 | #include "workspace.h" | ||
33 | #include "atoms.h" | 33 | #include "atoms.h" | ||
34 | #ifdef KWIN_BUILD_TABBOX | 34 | #ifdef KWIN_BUILD_TABBOX | ||
35 | #include "tabbox.h" | 35 | #include "tabbox.h" | ||
36 | #endif | 36 | #endif | ||
▲ Show 20 Lines • Show All 215 Lines • ▼ Show 20 Line(s) | 198 | { | |||
252 | case XCB_CONFIGURE_NOTIFY: | 252 | case XCB_CONFIGURE_NOTIFY: | ||
253 | if (reinterpret_cast<xcb_configure_notify_event_t*>(e)->event == rootWindow()) | 253 | if (reinterpret_cast<xcb_configure_notify_event_t*>(e)->event == rootWindow()) | ||
254 | markXStackingOrderAsDirty(); | 254 | markXStackingOrderAsDirty(); | ||
255 | break; | 255 | break; | ||
256 | }; | 256 | }; | ||
257 | 257 | | |||
258 | const xcb_window_t eventWindow = findEventWindow(e); | 258 | const xcb_window_t eventWindow = findEventWindow(e); | ||
259 | if (eventWindow != XCB_WINDOW_NONE) { | 259 | if (eventWindow != XCB_WINDOW_NONE) { | ||
260 | if (Client* c = findClient(Predicate::WindowMatch, eventWindow)) { | 260 | if (X11Client *c = findClient(Predicate::WindowMatch, eventWindow)) { | ||
261 | if (c->windowEvent(e)) | 261 | if (c->windowEvent(e)) | ||
262 | return true; | 262 | return true; | ||
263 | } else if (Client* c = findClient(Predicate::WrapperIdMatch, eventWindow)) { | 263 | } else if (X11Client *c = findClient(Predicate::WrapperIdMatch, eventWindow)) { | ||
264 | if (c->windowEvent(e)) | 264 | if (c->windowEvent(e)) | ||
265 | return true; | 265 | return true; | ||
266 | } else if (Client* c = findClient(Predicate::FrameIdMatch, eventWindow)) { | 266 | } else if (X11Client *c = findClient(Predicate::FrameIdMatch, eventWindow)) { | ||
267 | if (c->windowEvent(e)) | 267 | if (c->windowEvent(e)) | ||
268 | return true; | 268 | return true; | ||
269 | } else if (Client *c = findClient(Predicate::InputIdMatch, eventWindow)) { | 269 | } else if (X11Client *c = findClient(Predicate::InputIdMatch, eventWindow)) { | ||
270 | if (c->windowEvent(e)) | 270 | if (c->windowEvent(e)) | ||
271 | return true; | 271 | return true; | ||
272 | } else if (Unmanaged* c = findUnmanaged(eventWindow)) { | 272 | } else if (Unmanaged* c = findUnmanaged(eventWindow)) { | ||
273 | if (c->windowEvent(e)) | 273 | if (c->windowEvent(e)) | ||
274 | return true; | 274 | return true; | ||
275 | } | 275 | } | ||
276 | } | 276 | } | ||
277 | 277 | | |||
Show All 18 Lines | 295 | case XCB_REPARENT_NOTIFY: { | |||
296 | //do not confuse Qt with these events. After all, _we_ are the | 296 | //do not confuse Qt with these events. After all, _we_ are the | ||
297 | //window manager who does the reparenting. | 297 | //window manager who does the reparenting. | ||
298 | return true; | 298 | return true; | ||
299 | } | 299 | } | ||
300 | case XCB_MAP_REQUEST: { | 300 | case XCB_MAP_REQUEST: { | ||
301 | updateXTime(); | 301 | updateXTime(); | ||
302 | 302 | | |||
303 | const auto *event = reinterpret_cast<xcb_map_request_event_t*>(e); | 303 | const auto *event = reinterpret_cast<xcb_map_request_event_t*>(e); | ||
304 | if (Client* c = findClient(Predicate::WindowMatch, event->window)) { | 304 | if (X11Client *c = findClient(Predicate::WindowMatch, event->window)) { | ||
305 | // e->xmaprequest.window is different from e->xany.window | 305 | // e->xmaprequest.window is different from e->xany.window | ||
306 | // TODO this shouldn't be necessary now | 306 | // TODO this shouldn't be necessary now | ||
307 | c->windowEvent(e); | 307 | c->windowEvent(e); | ||
308 | FocusChain::self()->update(c, FocusChain::Update); | 308 | FocusChain::self()->update(c, FocusChain::Update); | ||
309 | } else if ( true /*|| e->xmaprequest.parent != root */ ) { | 309 | } else if ( true /*|| e->xmaprequest.parent != root */ ) { | ||
310 | // NOTICE don't check for the parent being the root window, this breaks when some app unmaps | 310 | // NOTICE don't check for the parent being the root window, this breaks when some app unmaps | ||
311 | // a window, changes something and immediately maps it back, without giving KWin | 311 | // a window, changes something and immediately maps it back, without giving KWin | ||
312 | // a chance to reparent it back to root | 312 | // a chance to reparent it back to root | ||
313 | // since KWin can get MapRequest only for root window children and | 313 | // since KWin can get MapRequest only for root window children and | ||
314 | // children of WindowWrapper (=clients), the check is AFAIK useless anyway | 314 | // children of WindowWrapper (=clients), the check is AFAIK useless anyway | ||
315 | // NOTICE: The save-set support in Client::mapRequestEvent() actually requires that | 315 | // NOTICE: The save-set support in X11Client::mapRequestEvent() actually requires that | ||
316 | // this code doesn't check the parent to be root. | 316 | // this code doesn't check the parent to be root. | ||
317 | if (!createClient(event->window, false)) { | 317 | if (!createClient(event->window, false)) { | ||
318 | xcb_map_window(connection(), event->window); | 318 | xcb_map_window(connection(), event->window); | ||
319 | const uint32_t values[] = { XCB_STACK_MODE_ABOVE }; | 319 | const uint32_t values[] = { XCB_STACK_MODE_ABOVE }; | ||
320 | xcb_configure_window(connection(), event->window, XCB_CONFIG_WINDOW_STACK_MODE, values); | 320 | xcb_configure_window(connection(), event->window, XCB_CONFIG_WINDOW_STACK_MODE, values); | ||
321 | } | 321 | } | ||
322 | } | 322 | } | ||
323 | return true; | 323 | return true; | ||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Line(s) | |||||
406 | 406 | | |||
407 | // **************************************** | 407 | // **************************************** | ||
408 | // Client | 408 | // Client | ||
409 | // **************************************** | 409 | // **************************************** | ||
410 | 410 | | |||
411 | /** | 411 | /** | ||
412 | * General handler for XEvents concerning the client window | 412 | * General handler for XEvents concerning the client window | ||
413 | */ | 413 | */ | ||
414 | bool Client::windowEvent(xcb_generic_event_t *e) | 414 | bool X11Client::windowEvent(xcb_generic_event_t *e) | ||
415 | { | 415 | { | ||
416 | if (findEventWindow(e) == window()) { // avoid doing stuff on frame or wrapper | 416 | if (findEventWindow(e) == window()) { // avoid doing stuff on frame or wrapper | ||
417 | NET::Properties dirtyProperties; | 417 | NET::Properties dirtyProperties; | ||
418 | NET::Properties2 dirtyProperties2; | 418 | NET::Properties2 dirtyProperties2; | ||
419 | double old_opacity = opacity(); | 419 | double old_opacity = opacity(); | ||
420 | info->event(e, &dirtyProperties, &dirtyProperties2); // pass through the NET stuff | 420 | info->event(e, &dirtyProperties, &dirtyProperties2); // pass through the NET stuff | ||
421 | 421 | | |||
422 | if ((dirtyProperties & NET::WMName) != 0) | 422 | if ((dirtyProperties & NET::WMName) != 0) | ||
▲ Show 20 Lines • Show All 151 Lines • ▼ Show 20 Line(s) | 567 | default: | |||
574 | break; | 574 | break; | ||
575 | } | 575 | } | ||
576 | return true; // eat all events | 576 | return true; // eat all events | ||
577 | } | 577 | } | ||
578 | 578 | | |||
579 | /** | 579 | /** | ||
580 | * Handles map requests of the client window | 580 | * Handles map requests of the client window | ||
581 | */ | 581 | */ | ||
582 | bool Client::mapRequestEvent(xcb_map_request_event_t *e) | 582 | bool X11Client::mapRequestEvent(xcb_map_request_event_t *e) | ||
583 | { | 583 | { | ||
584 | if (e->window != window()) { | 584 | if (e->window != window()) { | ||
585 | // Special support for the save-set feature, which is a bit broken. | 585 | // Special support for the save-set feature, which is a bit broken. | ||
586 | // If there's a window from one client embedded in another one, | 586 | // If there's a window from one client embedded in another one, | ||
587 | // e.g. using XEMBED, and the embedder suddenly loses its X connection, | 587 | // e.g. using XEMBED, and the embedder suddenly loses its X connection, | ||
588 | // save-set will reparent the embedded window to its closest ancestor | 588 | // save-set will reparent the embedded window to its closest ancestor | ||
589 | // that will remains. Unfortunately, with reparenting window managers, | 589 | // that will remains. Unfortunately, with reparenting window managers, | ||
590 | // this is not the root window, but the frame (or in KWin's case, | 590 | // this is not the root window, but the frame (or in KWin's case, | ||
Show All 19 Lines | 609 | else | |||
610 | demandAttention(); | 610 | demandAttention(); | ||
611 | } | 611 | } | ||
612 | return true; | 612 | return true; | ||
613 | } | 613 | } | ||
614 | 614 | | |||
615 | /** | 615 | /** | ||
616 | * Handles unmap notify events of the client window | 616 | * Handles unmap notify events of the client window | ||
617 | */ | 617 | */ | ||
618 | void Client::unmapNotifyEvent(xcb_unmap_notify_event_t *e) | 618 | void X11Client::unmapNotifyEvent(xcb_unmap_notify_event_t *e) | ||
619 | { | 619 | { | ||
620 | if (e->window != window()) | 620 | if (e->window != window()) | ||
621 | return; | 621 | return; | ||
622 | if (e->event != wrapperId()) { | 622 | if (e->event != wrapperId()) { | ||
623 | // most probably event from root window when initially reparenting | 623 | // most probably event from root window when initially reparenting | ||
624 | bool ignore = true; | 624 | bool ignore = true; | ||
625 | if (e->event == rootWindow() && (e->response_type & 0x80)) | 625 | if (e->event == rootWindow() && (e->response_type & 0x80)) | ||
626 | ignore = false; // XWithdrawWindow() | 626 | ignore = false; // XWithdrawWindow() | ||
627 | if (ignore) | 627 | if (ignore) | ||
628 | return; | 628 | return; | ||
629 | } | 629 | } | ||
630 | 630 | | |||
631 | // check whether this is result of an XReparentWindow - client then won't be parented by wrapper | 631 | // check whether this is result of an XReparentWindow - client then won't be parented by wrapper | ||
632 | // in this case do not release the client (causes reparent to root, removal from saveSet and what not) | 632 | // in this case do not release the client (causes reparent to root, removal from saveSet and what not) | ||
633 | // but just destroy the client | 633 | // but just destroy the client | ||
634 | Xcb::Tree tree(m_client); | 634 | Xcb::Tree tree(m_client); | ||
635 | xcb_window_t daddy = tree.parent(); | 635 | xcb_window_t daddy = tree.parent(); | ||
636 | if (daddy == m_wrapper) { | 636 | if (daddy == m_wrapper) { | ||
637 | releaseWindow(); // unmapped from a regular client state | 637 | releaseWindow(); // unmapped from a regular client state | ||
638 | } else { | 638 | } else { | ||
639 | destroyClient(); // the client was moved to some other parent | 639 | destroyClient(); // the client was moved to some other parent | ||
640 | } | 640 | } | ||
641 | } | 641 | } | ||
642 | 642 | | |||
643 | void Client::destroyNotifyEvent(xcb_destroy_notify_event_t *e) | 643 | void X11Client::destroyNotifyEvent(xcb_destroy_notify_event_t *e) | ||
644 | { | 644 | { | ||
645 | if (e->window != window()) | 645 | if (e->window != window()) | ||
646 | return; | 646 | return; | ||
647 | destroyClient(); | 647 | destroyClient(); | ||
648 | } | 648 | } | ||
649 | 649 | | |||
650 | 650 | | |||
651 | /** | 651 | /** | ||
652 | * Handles client messages for the client window | 652 | * Handles client messages for the client window | ||
653 | */ | 653 | */ | ||
654 | void Client::clientMessageEvent(xcb_client_message_event_t *e) | 654 | void X11Client::clientMessageEvent(xcb_client_message_event_t *e) | ||
655 | { | 655 | { | ||
656 | Toplevel::clientMessageEvent(e); | 656 | Toplevel::clientMessageEvent(e); | ||
657 | if (e->window != window()) | 657 | if (e->window != window()) | ||
658 | return; // ignore frame/wrapper | 658 | return; // ignore frame/wrapper | ||
659 | // WM_STATE | 659 | // WM_STATE | ||
660 | if (e->type == atoms->wm_change_state) { | 660 | if (e->type == atoms->wm_change_state) { | ||
661 | if (e->data.data32[0] == XCB_ICCCM_WM_STATE_ICONIC) | 661 | if (e->data.data32[0] == XCB_ICCCM_WM_STATE_ICONIC) | ||
662 | minimize(); | 662 | minimize(); | ||
663 | return; | 663 | return; | ||
664 | } | 664 | } | ||
665 | } | 665 | } | ||
666 | 666 | | |||
667 | 667 | | |||
668 | /** | 668 | /** | ||
669 | * Handles configure requests of the client window | 669 | * Handles configure requests of the client window | ||
670 | */ | 670 | */ | ||
671 | void Client::configureRequestEvent(xcb_configure_request_event_t *e) | 671 | void X11Client::configureRequestEvent(xcb_configure_request_event_t *e) | ||
672 | { | 672 | { | ||
673 | if (e->window != window()) | 673 | if (e->window != window()) | ||
674 | return; // ignore frame/wrapper | 674 | return; // ignore frame/wrapper | ||
675 | if (isResize() || isMove()) | 675 | if (isResize() || isMove()) | ||
676 | return; // we have better things to do right now | 676 | return; // we have better things to do right now | ||
677 | 677 | | |||
678 | if (m_fullscreenMode == FullScreenNormal) { // refuse resizing of fullscreen windows | 678 | if (m_fullscreenMode == FullScreenNormal) { // refuse resizing of fullscreen windows | ||
679 | // but allow resizing fullscreen hacks in order to let them cancel fullscreen mode | 679 | // but allow resizing fullscreen hacks in order to let them cancel fullscreen mode | ||
Show All 15 Lines | |||||
695 | 695 | | |||
696 | if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) | 696 | if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) | ||
697 | restackWindow(e->sibling, e->stack_mode, NET::FromApplication, userTime(), false); | 697 | restackWindow(e->sibling, e->stack_mode, NET::FromApplication, userTime(), false); | ||
698 | 698 | | |||
699 | // Sending a synthetic configure notify always is fine, even in cases where | 699 | // Sending a synthetic configure notify always is fine, even in cases where | ||
700 | // the ICCCM doesn't require this - it can be though of as 'the WM decided to move | 700 | // the ICCCM doesn't require this - it can be though of as 'the WM decided to move | ||
701 | // the window later'. The client should not cause that many configure request, | 701 | // the window later'. The client should not cause that many configure request, | ||
702 | // so this should not have any significant impact. With user moving/resizing | 702 | // so this should not have any significant impact. With user moving/resizing | ||
703 | // the it should be optimized though (see also Client::setGeometry()/plainResize()/move()). | 703 | // the it should be optimized though (see also X11Client::setGeometry()/plainResize()/move()). | ||
704 | sendSyntheticConfigureNotify(); | 704 | sendSyntheticConfigureNotify(); | ||
705 | 705 | | |||
706 | // SELI TODO accept configure requests for isDesktop windows (because kdesktop | 706 | // SELI TODO accept configure requests for isDesktop windows (because kdesktop | ||
707 | // may get XRANDR resize event before kwin), but check it's still at the bottom? | 707 | // may get XRANDR resize event before kwin), but check it's still at the bottom? | ||
708 | } | 708 | } | ||
709 | 709 | | |||
710 | 710 | | |||
711 | /** | 711 | /** | ||
712 | * Handles property changes of the client window | 712 | * Handles property changes of the client window | ||
713 | */ | 713 | */ | ||
714 | void Client::propertyNotifyEvent(xcb_property_notify_event_t *e) | 714 | void X11Client::propertyNotifyEvent(xcb_property_notify_event_t *e) | ||
715 | { | 715 | { | ||
716 | Toplevel::propertyNotifyEvent(e); | 716 | Toplevel::propertyNotifyEvent(e); | ||
717 | if (e->window != window()) | 717 | if (e->window != window()) | ||
718 | return; // ignore frame/wrapper | 718 | return; // ignore frame/wrapper | ||
719 | switch(e->atom) { | 719 | switch(e->atom) { | ||
720 | case XCB_ATOM_WM_NORMAL_HINTS: | 720 | case XCB_ATOM_WM_NORMAL_HINTS: | ||
721 | getWmNormalHints(); | 721 | getWmNormalHints(); | ||
722 | break; | 722 | break; | ||
Show All 28 Lines | 750 | else if (e->atom == atoms->kde_net_wm_appmenu_service_name) | |||
751 | checkApplicationMenuServiceName(); | 751 | checkApplicationMenuServiceName(); | ||
752 | else if (e->atom == atoms->kde_net_wm_appmenu_object_path) | 752 | else if (e->atom == atoms->kde_net_wm_appmenu_object_path) | ||
753 | checkApplicationMenuObjectPath(); | 753 | checkApplicationMenuObjectPath(); | ||
754 | break; | 754 | break; | ||
755 | } | 755 | } | ||
756 | } | 756 | } | ||
757 | 757 | | |||
758 | 758 | | |||
759 | void Client::enterNotifyEvent(xcb_enter_notify_event_t *e) | 759 | void X11Client::enterNotifyEvent(xcb_enter_notify_event_t *e) | ||
760 | { | 760 | { | ||
761 | if (e->event != frameId()) | 761 | if (e->event != frameId()) | ||
762 | return; // care only about entering the whole frame | 762 | return; // care only about entering the whole frame | ||
763 | 763 | | |||
764 | #define MOUSE_DRIVEN_FOCUS (!options->focusPolicyIsReasonable() || \ | 764 | #define MOUSE_DRIVEN_FOCUS (!options->focusPolicyIsReasonable() || \ | ||
765 | (options->focusPolicy() == Options::FocusFollowsMouse && options->isNextFocusPrefersMouse())) | 765 | (options->focusPolicy() == Options::FocusFollowsMouse && options->isNextFocusPrefersMouse())) | ||
766 | if (e->mode == XCB_NOTIFY_MODE_NORMAL || (e->mode == XCB_NOTIFY_MODE_UNGRAB && MOUSE_DRIVEN_FOCUS)) { | 766 | if (e->mode == XCB_NOTIFY_MODE_NORMAL || (e->mode == XCB_NOTIFY_MODE_UNGRAB && MOUSE_DRIVEN_FOCUS)) { | ||
767 | 767 | | |||
768 | if (options->isShadeHover()) { | 768 | if (options->isShadeHover()) { | ||
769 | cancelShadeHoverTimer(); | 769 | cancelShadeHoverTimer(); | ||
770 | if (isShade()) { | 770 | if (isShade()) { | ||
771 | shadeHoverTimer = new QTimer(this); | 771 | shadeHoverTimer = new QTimer(this); | ||
772 | connect(shadeHoverTimer, SIGNAL(timeout()), this, SLOT(shadeHover())); | 772 | connect(shadeHoverTimer, SIGNAL(timeout()), this, SLOT(shadeHover())); | ||
773 | shadeHoverTimer->setSingleShot(true); | 773 | shadeHoverTimer->setSingleShot(true); | ||
774 | shadeHoverTimer->start(options->shadeHoverInterval()); | 774 | shadeHoverTimer->start(options->shadeHoverInterval()); | ||
775 | } | 775 | } | ||
776 | } | 776 | } | ||
777 | #undef MOUSE_DRIVEN_FOCUS | 777 | #undef MOUSE_DRIVEN_FOCUS | ||
778 | 778 | | |||
779 | enterEvent(QPoint(e->root_x, e->root_y)); | 779 | enterEvent(QPoint(e->root_x, e->root_y)); | ||
780 | return; | 780 | return; | ||
781 | } | 781 | } | ||
782 | } | 782 | } | ||
783 | 783 | | |||
784 | void Client::leaveNotifyEvent(xcb_leave_notify_event_t *e) | 784 | void X11Client::leaveNotifyEvent(xcb_leave_notify_event_t *e) | ||
785 | { | 785 | { | ||
786 | if (e->event != frameId()) | 786 | if (e->event != frameId()) | ||
787 | return; // care only about leaving the whole frame | 787 | return; // care only about leaving the whole frame | ||
788 | if (e->mode == XCB_NOTIFY_MODE_NORMAL) { | 788 | if (e->mode == XCB_NOTIFY_MODE_NORMAL) { | ||
789 | if (!isMoveResizePointerButtonDown()) { | 789 | if (!isMoveResizePointerButtonDown()) { | ||
790 | setMoveResizePointerMode(PositionCenter); | 790 | setMoveResizePointerMode(PositionCenter); | ||
791 | updateCursor(); | 791 | updateCursor(); | ||
792 | } | 792 | } | ||
Show All 32 Lines | |||||
825 | } | 825 | } | ||
826 | return; | 826 | return; | ||
827 | } | 827 | } | ||
828 | } | 828 | } | ||
829 | 829 | | |||
830 | #define XCapL KKeyServer::modXLock() | 830 | #define XCapL KKeyServer::modXLock() | ||
831 | #define XNumL KKeyServer::modXNumLock() | 831 | #define XNumL KKeyServer::modXNumLock() | ||
832 | #define XScrL KKeyServer::modXScrollLock() | 832 | #define XScrL KKeyServer::modXScrollLock() | ||
833 | void Client::grabButton(int modifier) | 833 | void X11Client::grabButton(int modifier) | ||
834 | { | 834 | { | ||
835 | unsigned int mods[ 8 ] = { | 835 | unsigned int mods[ 8 ] = { | ||
836 | 0, XCapL, XNumL, XNumL | XCapL, | 836 | 0, XCapL, XNumL, XNumL | XCapL, | ||
837 | XScrL, XScrL | XCapL, | 837 | XScrL, XScrL | XCapL, | ||
838 | XScrL | XNumL, XScrL | XNumL | XCapL | 838 | XScrL | XNumL, XScrL | XNumL | XCapL | ||
839 | }; | 839 | }; | ||
840 | for (int i = 0; | 840 | for (int i = 0; | ||
841 | i < 8; | 841 | i < 8; | ||
842 | ++i) | 842 | ++i) | ||
843 | m_wrapper.grabButton(XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, modifier | mods[ i ]); | 843 | m_wrapper.grabButton(XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, modifier | mods[ i ]); | ||
844 | } | 844 | } | ||
845 | 845 | | |||
846 | void Client::ungrabButton(int modifier) | 846 | void X11Client::ungrabButton(int modifier) | ||
847 | { | 847 | { | ||
848 | unsigned int mods[ 8 ] = { | 848 | unsigned int mods[ 8 ] = { | ||
849 | 0, XCapL, XNumL, XNumL | XCapL, | 849 | 0, XCapL, XNumL, XNumL | XCapL, | ||
850 | XScrL, XScrL | XCapL, | 850 | XScrL, XScrL | XCapL, | ||
851 | XScrL | XNumL, XScrL | XNumL | XCapL | 851 | XScrL | XNumL, XScrL | XNumL | XCapL | ||
852 | }; | 852 | }; | ||
853 | for (int i = 0; | 853 | for (int i = 0; | ||
854 | i < 8; | 854 | i < 8; | ||
855 | ++i) | 855 | ++i) | ||
856 | m_wrapper.ungrabButton(modifier | mods[ i ]); | 856 | m_wrapper.ungrabButton(modifier | mods[ i ]); | ||
857 | } | 857 | } | ||
858 | #undef XCapL | 858 | #undef XCapL | ||
859 | #undef XNumL | 859 | #undef XNumL | ||
860 | #undef XScrL | 860 | #undef XScrL | ||
861 | 861 | | |||
862 | /** | 862 | /** | ||
863 | * Releases the passive grab for some modifier combinations when a | 863 | * Releases the passive grab for some modifier combinations when a | ||
864 | * window becomes active. This helps broken X programs that | 864 | * window becomes active. This helps broken X programs that | ||
865 | * missinterpret LeaveNotify events in grab mode to work properly | 865 | * missinterpret LeaveNotify events in grab mode to work properly | ||
866 | * (Motif, AWT, Tk, ...) | 866 | * (Motif, AWT, Tk, ...) | ||
867 | */ | 867 | */ | ||
868 | void Client::updateMouseGrab() | 868 | void X11Client::updateMouseGrab() | ||
869 | { | 869 | { | ||
870 | if (workspace()->globalShortcutsDisabled()) { | 870 | if (workspace()->globalShortcutsDisabled()) { | ||
871 | m_wrapper.ungrabButton(); | 871 | m_wrapper.ungrabButton(); | ||
872 | // keep grab for the simple click without modifiers if needed (see below) | 872 | // keep grab for the simple click without modifiers if needed (see below) | ||
873 | bool not_obscured = workspace()->topClientOnDesktop(VirtualDesktopManager::self()->current(), -1, true, false) == this; | 873 | bool not_obscured = workspace()->topClientOnDesktop(VirtualDesktopManager::self()->current(), -1, true, false) == this; | ||
874 | if (!(!options->isClickRaise() || not_obscured)) | 874 | if (!(!options->isClickRaise() || not_obscured)) | ||
875 | grabButton(XCB_NONE); | 875 | grabButton(XCB_NONE); | ||
876 | return; | 876 | return; | ||
Show All 23 Lines | |||||
900 | static bool modKeyDown(int state) { | 900 | static bool modKeyDown(int state) { | ||
901 | const uint keyModX = (options->keyCmdAllModKey() == Qt::Key_Meta) ? | 901 | const uint keyModX = (options->keyCmdAllModKey() == Qt::Key_Meta) ? | ||
902 | KKeyServer::modXMeta() : KKeyServer::modXAlt(); | 902 | KKeyServer::modXMeta() : KKeyServer::modXAlt(); | ||
903 | return keyModX && (state & KKeyServer::accelModMaskX()) == keyModX; | 903 | return keyModX && (state & KKeyServer::accelModMaskX()) == keyModX; | ||
904 | } | 904 | } | ||
905 | 905 | | |||
906 | 906 | | |||
907 | // return value matters only when filtering events before decoration gets them | 907 | // return value matters only when filtering events before decoration gets them | ||
908 | bool Client::buttonPressEvent(xcb_window_t w, int button, int state, int x, int y, int x_root, int y_root, xcb_timestamp_t time) | 908 | bool X11Client::buttonPressEvent(xcb_window_t w, int button, int state, int x, int y, int x_root, int y_root, xcb_timestamp_t time) | ||
909 | { | 909 | { | ||
910 | if (isMoveResizePointerButtonDown()) { | 910 | if (isMoveResizePointerButtonDown()) { | ||
911 | if (w == wrapperId()) | 911 | if (w == wrapperId()) | ||
912 | xcb_allow_events(connection(), XCB_ALLOW_SYNC_POINTER, XCB_TIME_CURRENT_TIME); //xTime()); | 912 | xcb_allow_events(connection(), XCB_ALLOW_SYNC_POINTER, XCB_TIME_CURRENT_TIME); //xTime()); | ||
913 | return true; | 913 | return true; | ||
914 | } | 914 | } | ||
915 | 915 | | |||
916 | if (w == wrapperId() || w == frameId() || w == inputId()) { | 916 | if (w == wrapperId() || w == frameId() || w == inputId()) { | ||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Line(s) | 1006 | } else { | |||
1013 | } | 1013 | } | ||
1014 | } | 1014 | } | ||
1015 | return true; | 1015 | return true; | ||
1016 | } | 1016 | } | ||
1017 | return true; | 1017 | return true; | ||
1018 | } | 1018 | } | ||
1019 | 1019 | | |||
1020 | // return value matters only when filtering events before decoration gets them | 1020 | // return value matters only when filtering events before decoration gets them | ||
1021 | bool Client::buttonReleaseEvent(xcb_window_t w, int button, int state, int x, int y, int x_root, int y_root) | 1021 | bool X11Client::buttonReleaseEvent(xcb_window_t w, int button, int state, int x, int y, int x_root, int y_root) | ||
1022 | { | 1022 | { | ||
1023 | if (w == frameId() && isDecorated()) { | 1023 | if (w == frameId() && isDecorated()) { | ||
1024 | // wheel handled on buttonPress | 1024 | // wheel handled on buttonPress | ||
1025 | if (button < 4 || button > 7) { | 1025 | if (button < 4 || button > 7) { | ||
1026 | QMouseEvent event(QEvent::MouseButtonRelease, | 1026 | QMouseEvent event(QEvent::MouseButtonRelease, | ||
1027 | QPointF(x, y), | 1027 | QPointF(x, y), | ||
1028 | QPointF(x_root, y_root), | 1028 | QPointF(x_root, y_root), | ||
1029 | x11ToQtMouseButton(button), | 1029 | x11ToQtMouseButton(button), | ||
Show All 29 Lines | |||||
1059 | 1059 | | |||
1060 | if ((state & buttonMask) == 0) { | 1060 | if ((state & buttonMask) == 0) { | ||
1061 | endMoveResize(); | 1061 | endMoveResize(); | ||
1062 | } | 1062 | } | ||
1063 | return true; | 1063 | return true; | ||
1064 | } | 1064 | } | ||
1065 | 1065 | | |||
1066 | // return value matters only when filtering events before decoration gets them | 1066 | // return value matters only when filtering events before decoration gets them | ||
1067 | bool Client::motionNotifyEvent(xcb_window_t w, int state, int x, int y, int x_root, int y_root) | 1067 | bool X11Client::motionNotifyEvent(xcb_window_t w, int state, int x, int y, int x_root, int y_root) | ||
1068 | { | 1068 | { | ||
1069 | if (w == frameId() && isDecorated() && !isMinimized()) { | 1069 | if (w == frameId() && isDecorated() && !isMinimized()) { | ||
1070 | // TODO Mouse move event dependent on state | 1070 | // TODO Mouse move event dependent on state | ||
1071 | QHoverEvent event(QEvent::HoverMove, QPointF(x, y), QPointF(x, y)); | 1071 | QHoverEvent event(QEvent::HoverMove, QPointF(x, y), QPointF(x, y)); | ||
1072 | QCoreApplication::instance()->sendEvent(decoration(), &event); | 1072 | QCoreApplication::instance()->sendEvent(decoration(), &event); | ||
1073 | } | 1073 | } | ||
1074 | if (w != frameId() && w != inputId() && w != moveResizeGrabWindow()) | 1074 | if (w != frameId() && w != inputId() && w != moveResizeGrabWindow()) | ||
1075 | return true; // care only about the whole frame | 1075 | return true; // care only about the whole frame | ||
Show All 18 Lines | 1093 | if (w == moveResizeGrabWindow()) { | |||
1094 | x = this->x(); // translate from grab window to local coords | 1094 | x = this->x(); // translate from grab window to local coords | ||
1095 | y = this->y(); | 1095 | y = this->y(); | ||
1096 | } | 1096 | } | ||
1097 | 1097 | | |||
1098 | handleMoveResize(QPoint(x, y), QPoint(x_root, y_root)); | 1098 | handleMoveResize(QPoint(x, y), QPoint(x_root, y_root)); | ||
1099 | return true; | 1099 | return true; | ||
1100 | } | 1100 | } | ||
1101 | 1101 | | |||
1102 | void Client::focusInEvent(xcb_focus_in_event_t *e) | 1102 | void X11Client::focusInEvent(xcb_focus_in_event_t *e) | ||
1103 | { | 1103 | { | ||
1104 | if (e->event != window()) | 1104 | if (e->event != window()) | ||
1105 | return; // only window gets focus | 1105 | return; // only window gets focus | ||
1106 | if (e->mode == XCB_NOTIFY_MODE_UNGRAB) | 1106 | if (e->mode == XCB_NOTIFY_MODE_UNGRAB) | ||
1107 | return; // we don't care | 1107 | return; // we don't care | ||
1108 | if (e->detail == XCB_NOTIFY_DETAIL_POINTER) | 1108 | if (e->detail == XCB_NOTIFY_DETAIL_POINTER) | ||
1109 | return; // we don't care | 1109 | return; // we don't care | ||
1110 | if (!isShown(false) || !isOnCurrentDesktop()) // we unmapped it, but it got focus meanwhile -> | 1110 | if (!isShown(false) || !isOnCurrentDesktop()) // we unmapped it, but it got focus meanwhile -> | ||
1111 | return; // activateNextClient() already transferred focus elsewhere | 1111 | return; // activateNextClient() already transferred focus elsewhere | ||
1112 | workspace()->forEachClient([](Client *client) { | 1112 | workspace()->forEachClient([](X11Client *client) { | ||
1113 | client->cancelFocusOutTimer(); | 1113 | client->cancelFocusOutTimer(); | ||
1114 | }); | 1114 | }); | ||
1115 | // check if this client is in should_get_focus list or if activation is allowed | 1115 | // check if this client is in should_get_focus list or if activation is allowed | ||
1116 | bool activate = workspace()->allowClientActivation(this, -1U, true); | 1116 | bool activate = workspace()->allowClientActivation(this, -1U, true); | ||
1117 | workspace()->gotFocusIn(this); // remove from should_get_focus list | 1117 | workspace()->gotFocusIn(this); // remove from should_get_focus list | ||
1118 | if (activate) | 1118 | if (activate) | ||
1119 | setActive(true); | 1119 | setActive(true); | ||
1120 | else { | 1120 | else { | ||
1121 | workspace()->restoreFocus(); | 1121 | workspace()->restoreFocus(); | ||
1122 | demandAttention(); | 1122 | demandAttention(); | ||
1123 | } | 1123 | } | ||
1124 | } | 1124 | } | ||
1125 | 1125 | | |||
1126 | void Client::focusOutEvent(xcb_focus_out_event_t *e) | 1126 | void X11Client::focusOutEvent(xcb_focus_out_event_t *e) | ||
1127 | { | 1127 | { | ||
1128 | if (e->event != window()) | 1128 | if (e->event != window()) | ||
1129 | return; // only window gets focus | 1129 | return; // only window gets focus | ||
1130 | if (e->mode == XCB_NOTIFY_MODE_GRAB) | 1130 | if (e->mode == XCB_NOTIFY_MODE_GRAB) | ||
1131 | return; // we don't care | 1131 | return; // we don't care | ||
1132 | if (isShade()) | 1132 | if (isShade()) | ||
1133 | return; // here neither | 1133 | return; // here neither | ||
1134 | if (e->detail != XCB_NOTIFY_DETAIL_NONLINEAR | 1134 | if (e->detail != XCB_NOTIFY_DETAIL_NONLINEAR | ||
1135 | && e->detail != XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL) | 1135 | && e->detail != XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL) | ||
1136 | // SELI check all this | 1136 | // SELI check all this | ||
1137 | return; // hack for motif apps like netscape | 1137 | return; // hack for motif apps like netscape | ||
1138 | if (QApplication::activePopupWidget()) | 1138 | if (QApplication::activePopupWidget()) | ||
1139 | return; | 1139 | return; | ||
1140 | 1140 | | |||
1141 | // When a client loses focus, FocusOut events are usually immediatelly | 1141 | // When a client loses focus, FocusOut events are usually immediatelly | ||
1142 | // followed by FocusIn events for another client that gains the focus | 1142 | // followed by FocusIn events for another client that gains the focus | ||
1143 | // (unless the focus goes to another screen, or to the nofocus widget). | 1143 | // (unless the focus goes to another screen, or to the nofocus widget). | ||
1144 | // Without this check, the former focused client would have to be | 1144 | // Without this check, the former focused client would have to be | ||
1145 | // deactivated, and after that, the new one would be activated, with | 1145 | // deactivated, and after that, the new one would be activated, with | ||
1146 | // a short time when there would be no active client. This can cause | 1146 | // a short time when there would be no active client. This can cause | ||
1147 | // flicker sometimes, e.g. when a fullscreen is shown, and focus is transferred | 1147 | // flicker sometimes, e.g. when a fullscreen is shown, and focus is transferred | ||
1148 | // from it to its transient, the fullscreen would be kept in the Active layer | 1148 | // from it to its transient, the fullscreen would be kept in the Active layer | ||
1149 | // at the beginning and at the end, but not in the middle, when the active | 1149 | // at the beginning and at the end, but not in the middle, when the active | ||
1150 | // client would be temporarily none (see Client::belongToLayer() ). | 1150 | // client would be temporarily none (see X11Client::belongToLayer() ). | ||
1151 | // Therefore the setActive(false) call is moved to the end of the current | 1151 | // Therefore the setActive(false) call is moved to the end of the current | ||
1152 | // event queue. If there is a matching FocusIn event in the current queue | 1152 | // event queue. If there is a matching FocusIn event in the current queue | ||
1153 | // this will be processed before the setActive(false) call and the activation | 1153 | // this will be processed before the setActive(false) call and the activation | ||
1154 | // of the Client which gained FocusIn will automatically deactivate the | 1154 | // of the Client which gained FocusIn will automatically deactivate the | ||
1155 | // previously active client. | 1155 | // previously active client. | ||
1156 | if (!m_focusOutTimer) { | 1156 | if (!m_focusOutTimer) { | ||
1157 | m_focusOutTimer = new QTimer(this); | 1157 | m_focusOutTimer = new QTimer(this); | ||
1158 | m_focusOutTimer->setSingleShot(true); | 1158 | m_focusOutTimer->setSingleShot(true); | ||
1159 | m_focusOutTimer->setInterval(0); | 1159 | m_focusOutTimer->setInterval(0); | ||
1160 | connect(m_focusOutTimer, &QTimer::timeout, [this]() { | 1160 | connect(m_focusOutTimer, &QTimer::timeout, [this]() { | ||
1161 | setActive(false); | 1161 | setActive(false); | ||
1162 | }); | 1162 | }); | ||
1163 | } | 1163 | } | ||
1164 | m_focusOutTimer->start(); | 1164 | m_focusOutTimer->start(); | ||
1165 | } | 1165 | } | ||
1166 | 1166 | | |||
1167 | // performs _NET_WM_MOVERESIZE | 1167 | // performs _NET_WM_MOVERESIZE | ||
1168 | void Client::NETMoveResize(int x_root, int y_root, NET::Direction direction) | 1168 | void X11Client::NETMoveResize(int x_root, int y_root, NET::Direction direction) | ||
1169 | { | 1169 | { | ||
1170 | if (direction == NET::Move) { | 1170 | if (direction == NET::Move) { | ||
1171 | // move cursor to the provided position to prevent the window jumping there on first movement | 1171 | // move cursor to the provided position to prevent the window jumping there on first movement | ||
1172 | // the expectation is that the cursor is already at the provided position, | 1172 | // the expectation is that the cursor is already at the provided position, | ||
1173 | // thus it's more a safety measurement | 1173 | // thus it's more a safety measurement | ||
1174 | Cursor::setPos(QPoint(x_root, y_root)); | 1174 | Cursor::setPos(QPoint(x_root, y_root)); | ||
1175 | performMouseCommand(Options::MouseMove, QPoint(x_root, y_root)); | 1175 | performMouseCommand(Options::MouseMove, QPoint(x_root, y_root)); | ||
1176 | } else if (isMoveResize() && direction == NET::MoveResizeCancel) { | 1176 | } else if (isMoveResize() && direction == NET::MoveResizeCancel) { | ||
Show All 29 Lines | 1203 | } else if (direction == NET::KeyboardMove) { | |||
1206 | performMouseCommand(Options::MouseUnrestrictedMove, geometry().center()); | 1206 | performMouseCommand(Options::MouseUnrestrictedMove, geometry().center()); | ||
1207 | } else if (direction == NET::KeyboardSize) { | 1207 | } else if (direction == NET::KeyboardSize) { | ||
1208 | // ignore mouse coordinates given in the message, mouse position is used by the resizing algorithm | 1208 | // ignore mouse coordinates given in the message, mouse position is used by the resizing algorithm | ||
1209 | Cursor::setPos(geometry().bottomRight()); | 1209 | Cursor::setPos(geometry().bottomRight()); | ||
1210 | performMouseCommand(Options::MouseUnrestrictedResize, geometry().bottomRight()); | 1210 | performMouseCommand(Options::MouseUnrestrictedResize, geometry().bottomRight()); | ||
1211 | } | 1211 | } | ||
1212 | } | 1212 | } | ||
1213 | 1213 | | |||
1214 | void Client::keyPressEvent(uint key_code, xcb_timestamp_t time) | 1214 | void X11Client::keyPressEvent(uint key_code, xcb_timestamp_t time) | ||
1215 | { | 1215 | { | ||
1216 | updateUserTime(time); | 1216 | updateUserTime(time); | ||
1217 | AbstractClient::keyPressEvent(key_code); | 1217 | AbstractClient::keyPressEvent(key_code); | ||
1218 | } | 1218 | } | ||
1219 | 1219 | | |||
1220 | // **************************************** | 1220 | // **************************************** | ||
1221 | // Unmanaged | 1221 | // Unmanaged | ||
1222 | // **************************************** | 1222 | // **************************************** | ||
▲ Show 20 Lines • Show All 123 Lines • Show Last 20 Lines |