diff options
Diffstat (limited to 'src/Ewmh.cc')
-rw-r--r-- | src/Ewmh.cc | 107 |
1 files changed, 85 insertions, 22 deletions
diff --git a/src/Ewmh.cc b/src/Ewmh.cc index b6c5b24..78ea63e 100644 --- a/src/Ewmh.cc +++ b/src/Ewmh.cc | |||
@@ -60,10 +60,28 @@ Ewmh::~Ewmh() { | |||
60 | void Ewmh::initForScreen(BScreen &screen) { | 60 | void Ewmh::initForScreen(BScreen &screen) { |
61 | Display *disp = FbTk::App::instance()->display(); | 61 | Display *disp = FbTk::App::instance()->display(); |
62 | 62 | ||
63 | /* From Extended Window Manager Hints, draft 1.3: | ||
64 | * | ||
65 | * _NET_SUPPORTING_WM_CHECK | ||
66 | * | ||
67 | * The Window Manager MUST set this property on the root window | ||
68 | * to be the ID of a child window created by himself, to indicate | ||
69 | * that a compliant window manager is active. The child window | ||
70 | * MUST also have the _NET_SUPPORTING_WM_CHECK property set to | ||
71 | * the ID of the child window. The child window MUST also have | ||
72 | * the _NET_WM_NAME property set to the name of the Window Manager. | ||
73 | * | ||
74 | * Rationale: The child window is used to distinguish an active | ||
75 | * Window Manager from a stale _NET_SUPPORTING_WM_CHECK property | ||
76 | * that happens to point to another window. If the | ||
77 | * _NET_SUPPORTING_WM_CHECK window on the client window is missing | ||
78 | * or not properly set, clients SHOULD assume that no conforming | ||
79 | * Window Manager is present. | ||
80 | */ | ||
63 | 81 | ||
64 | Window wincheck = XCreateSimpleWindow(disp, | 82 | Window wincheck = XCreateSimpleWindow(disp, |
65 | screen.rootWindow().window(), | 83 | screen.rootWindow().window(), |
66 | 0, 0, 5, 5, 0, 0, 0); | 84 | -10, -10, 5, 5, 0, 0, 0); |
67 | 85 | ||
68 | if (wincheck != None) { | 86 | if (wincheck != None) { |
69 | // store the window so we can delete it later | 87 | // store the window so we can delete it later |
@@ -72,10 +90,10 @@ void Ewmh::initForScreen(BScreen &screen) { | |||
72 | screen.rootWindow().changeProperty(m_net_supporting_wm_check, XA_WINDOW, 32, | 90 | screen.rootWindow().changeProperty(m_net_supporting_wm_check, XA_WINDOW, 32, |
73 | PropModeReplace, (unsigned char *) &wincheck, 1); | 91 | PropModeReplace, (unsigned char *) &wincheck, 1); |
74 | XChangeProperty(disp, wincheck, m_net_supporting_wm_check, XA_WINDOW, 32, | 92 | XChangeProperty(disp, wincheck, m_net_supporting_wm_check, XA_WINDOW, 32, |
75 | PropModeReplace, (unsigned char *) &wincheck, 1); | 93 | PropModeReplace, (unsigned char *) &wincheck, 1); |
76 | 94 | ||
77 | XChangeProperty(disp, wincheck, m_net_wm_name, XA_STRING, 8, | 95 | XChangeProperty(disp, wincheck, m_net_wm_name, XA_STRING, 8, |
78 | PropModeReplace, (unsigned char *) "Fluxbox", strlen("Fluxbox")); | 96 | PropModeReplace, (unsigned char *) "Fluxbox", strlen("Fluxbox")); |
79 | } | 97 | } |
80 | 98 | ||
81 | //set supported atoms | 99 | //set supported atoms |
@@ -86,9 +104,9 @@ void Ewmh::initForScreen(BScreen &screen) { | |||
86 | // states that we support: | 104 | // states that we support: |
87 | m_net_wm_state_sticky, | 105 | m_net_wm_state_sticky, |
88 | m_net_wm_state_shaded, | 106 | m_net_wm_state_shaded, |
89 | m_net_wm_state_maximized_horz, | 107 | m_net_wm_state_maximized_horz, |
90 | m_net_wm_state_maximized_vert, | 108 | m_net_wm_state_maximized_vert, |
91 | m_net_wm_state_fullscreen, | 109 | m_net_wm_state_fullscreen, |
92 | m_net_wm_state_hidden, | 110 | m_net_wm_state_hidden, |
93 | m_net_wm_state_skip_taskbar, | 111 | m_net_wm_state_skip_taskbar, |
94 | 112 | ||
@@ -170,6 +188,7 @@ void Ewmh::setupFrame(FluxboxWindow &win) { | |||
170 | * Managers that do not recognize the extensions. | 188 | * Managers that do not recognize the extensions. |
171 | * | 189 | * |
172 | */ | 190 | */ |
191 | |||
173 | win.winClient().property(m_net_wm_window_type, 0, 0x7fffffff, False, XA_ATOM, | 192 | win.winClient().property(m_net_wm_window_type, 0, 0x7fffffff, False, XA_ATOM, |
174 | &ret_type, &fmt, &nitems, &bytes_after, | 193 | &ret_type, &fmt, &nitems, &bytes_after, |
175 | &data); | 194 | &data); |
@@ -501,7 +520,39 @@ void Ewmh::updateWorkarea(BScreen &screen) { | |||
501 | } | 520 | } |
502 | 521 | ||
503 | void Ewmh::updateState(FluxboxWindow &win) { | 522 | void Ewmh::updateState(FluxboxWindow &win) { |
504 | //!! TODO | 523 | |
524 | // TODO: should we update the _NET_WM_ALLOWED_ACTIONS | ||
525 | // here too? | ||
526 | |||
527 | std::vector<unsigned int> state; | ||
528 | |||
529 | if (win.isStuck()) | ||
530 | state.push_back(m_net_wm_state_sticky); | ||
531 | if (win.isShaded()) | ||
532 | state.push_back(m_net_wm_state_shaded); | ||
533 | if (win.layerNum() == Fluxbox::instance()->getBottomLayer()) | ||
534 | state.push_back(m_net_wm_state_below); | ||
535 | if (win.layerNum() == Fluxbox::instance()->getAboveDockLayer()) | ||
536 | state.push_back(m_net_wm_state_above); | ||
537 | if (win.isFocusHidden()) { | ||
538 | state.push_back(m_net_wm_state_hidden); | ||
539 | state.push_back(m_net_wm_state_skip_taskbar); | ||
540 | } | ||
541 | if (win.isFullscreen()) { | ||
542 | state.push_back(m_net_wm_state_fullscreen); | ||
543 | } | ||
544 | |||
545 | FluxboxWindow::ClientList::iterator it = win.clientList().begin(); | ||
546 | FluxboxWindow::ClientList::iterator it_end = win.clientList().end(); | ||
547 | |||
548 | it = win.clientList().begin(); | ||
549 | for (; it != it_end; ++it) { | ||
550 | if (!state.empty()) | ||
551 | (*it)->changeProperty(m_net_wm_state, XA_ATOM, 32, PropModeReplace, | ||
552 | reinterpret_cast<unsigned char*>(&state.front()), state.size()); | ||
553 | else | ||
554 | (*it)->deleteProperty(m_net_wm_state); | ||
555 | } | ||
505 | } | 556 | } |
506 | 557 | ||
507 | void Ewmh::updateLayer(FluxboxWindow &win) { | 558 | void Ewmh::updateLayer(FluxboxWindow &win) { |
@@ -537,6 +588,7 @@ void Ewmh::updateWorkspace(FluxboxWindow &win) { | |||
537 | // return true if we did handle the atom here | 588 | // return true if we did handle the atom here |
538 | bool Ewmh::checkClientMessage(const XClientMessageEvent &ce, | 589 | bool Ewmh::checkClientMessage(const XClientMessageEvent &ce, |
539 | BScreen * screen, WinClient * const winclient) { | 590 | BScreen * screen, WinClient * const winclient) { |
591 | |||
540 | if (ce.message_type == m_net_wm_desktop) { | 592 | if (ce.message_type == m_net_wm_desktop) { |
541 | // ce.data.l[0] = workspace number | 593 | // ce.data.l[0] = workspace number |
542 | // valid window | 594 | // valid window |
@@ -581,7 +633,6 @@ bool Ewmh::checkClientMessage(const XClientMessageEvent &ce, | |||
581 | toggleState(win, ce.data.l[1]); | 633 | toggleState(win, ce.data.l[1]); |
582 | toggleState(win, ce.data.l[2]); | 634 | toggleState(win, ce.data.l[2]); |
583 | } | 635 | } |
584 | |||
585 | return true; | 636 | return true; |
586 | } else if (ce.message_type == m_net_number_of_desktops) { | 637 | } else if (ce.message_type == m_net_number_of_desktops) { |
587 | if (screen == 0) | 638 | if (screen == 0) |
@@ -676,7 +727,7 @@ bool Ewmh::propertyNotify(WinClient &winclient, Atom the_property) { | |||
676 | #endif // DEBUG | 727 | #endif // DEBUG |
677 | updateStrut(winclient); | 728 | updateStrut(winclient); |
678 | return true; | 729 | return true; |
679 | } | 730 | } |
680 | 731 | ||
681 | return false; | 732 | return false; |
682 | } | 733 | } |
@@ -725,6 +776,18 @@ void Ewmh::createAtoms() { | |||
725 | m_net_wm_state_above = XInternAtom(disp, "_NET_WM_STATE_ABOVE", False); | 776 | m_net_wm_state_above = XInternAtom(disp, "_NET_WM_STATE_ABOVE", False); |
726 | m_net_wm_state_below = XInternAtom(disp, "_NET_WM_STATE_BELOW", False); | 777 | m_net_wm_state_below = XInternAtom(disp, "_NET_WM_STATE_BELOW", False); |
727 | 778 | ||
779 | // allowed actions | ||
780 | m_net_wm_allowed_actions = XInternAtom(disp, "_NET_WM_ALLOWED_ACTIONS", False); | ||
781 | m_net_wm_action_move = XInternAtom(disp, "_NET_WM_ACTIONS_MOVE", False); | ||
782 | m_net_wm_action_resize = XInternAtom(disp, "_NET_WM_ACTIONS_RESIZE", False); | ||
783 | m_net_wm_action_minimize = XInternAtom(disp, "_NET_WM_ACTIONS_MINIMIZE", False); | ||
784 | m_net_wm_action_shade = XInternAtom(disp, "_NET_WM_ACTIONS_SHADE", False); | ||
785 | m_net_wm_action_stick = XInternAtom(disp, "_NET_WM_ACTIONS_STICK", False); | ||
786 | m_net_wm_action_maximize_horz = XInternAtom(disp, "_NET_WM_ACTIONS_MAXIMIZE_HORZ", False); | ||
787 | m_net_wm_action_maximize_vert = XInternAtom(disp, "_NET_WM_ACTIONS_MAXIMIZE_VERT", False); | ||
788 | m_net_wm_action_fullscreen = XInternAtom(disp, "_NET_WM_ACTIONS_FULLSCREEN", False); | ||
789 | m_net_wm_action_change_desktop = XInternAtom(disp, "_NET_WM_ACTIONS_CHANGE_DESKTOP", False); | ||
790 | m_net_wm_action_close = XInternAtom(disp, "_NET_WM_ACTIONS_CLOSE", False); | ||
728 | 791 | ||
729 | m_net_wm_strut = XInternAtom(disp, "_NET_WM_STRUT", False); | 792 | m_net_wm_strut = XInternAtom(disp, "_NET_WM_STRUT", False); |
730 | m_net_wm_icon_geometry = XInternAtom(disp, "_NET_WM_ICON_GEOMETRY", False); | 793 | m_net_wm_icon_geometry = XInternAtom(disp, "_NET_WM_ICON_GEOMETRY", False); |
@@ -739,6 +802,12 @@ void Ewmh::createAtoms() { | |||
739 | void Ewmh::setFullscreen(FluxboxWindow &win, bool value) { | 802 | void Ewmh::setFullscreen(FluxboxWindow &win, bool value) { |
740 | // fullscreen implies maximised, above dock layer, | 803 | // fullscreen implies maximised, above dock layer, |
741 | // and no decorations (or decorations offscreen) | 804 | // and no decorations (or decorations offscreen) |
805 | // | ||
806 | // TODO: do we need the WindowState etc here anymore? | ||
807 | // FluxboxWindow::setFullscreen() remembering old values | ||
808 | // already and set them... | ||
809 | // only reason i can see is that the user manually | ||
810 | // moved the (fullscreened) window | ||
742 | WindowState *saved_state = getState(win); | 811 | WindowState *saved_state = getState(win); |
743 | if (value) { | 812 | if (value) { |
744 | // fullscreen on | 813 | // fullscreen on |
@@ -746,25 +815,17 @@ void Ewmh::setFullscreen(FluxboxWindow &win, bool value) { | |||
746 | saved_state = new WindowState(win.x(), win.y(), win.width(), | 815 | saved_state = new WindowState(win.x(), win.y(), win.width(), |
747 | win.height(), win.layerNum(), win.decorationMask()); | 816 | win.height(), win.layerNum(), win.decorationMask()); |
748 | saveState(win, saved_state); | 817 | saveState(win, saved_state); |
749 | 818 | win.setFullscreen(true); | |
750 | // actually make it fullscreen | ||
751 | |||
752 | // clear decorations | ||
753 | win.setDecorationMask(0); | ||
754 | |||
755 | // be xinerama aware | ||
756 | BScreen &screen = win.screen(); | ||
757 | int head = screen.getHead(win.fbWindow()); | ||
758 | win.moveResize(screen.getHeadX(head), screen.getHeadY(head), | ||
759 | screen.getHeadWidth(head), screen.getHeadHeight(head)); | ||
760 | win.moveToLayer(Fluxbox::instance()->getAboveDockLayer()); | ||
761 | } | 819 | } |
762 | } else { // turn off fullscreen | 820 | } else { // turn off fullscreen |
763 | if (saved_state) { // no saved state, can't restore it | 821 | if (saved_state) { // no saved state, can't restore it |
822 | win.setFullscreen(false); | ||
823 | /* | ||
764 | win.setDecorationMask(saved_state->decor); | 824 | win.setDecorationMask(saved_state->decor); |
765 | win.moveResize(saved_state->x, saved_state->y, | 825 | win.moveResize(saved_state->x, saved_state->y, |
766 | saved_state->width, saved_state->height); | 826 | saved_state->width, saved_state->height); |
767 | win.moveToLayer(saved_state->layer); | 827 | win.moveToLayer(saved_state->layer); |
828 | */ | ||
768 | clearState(win); | 829 | clearState(win); |
769 | saved_state = 0; | 830 | saved_state = 0; |
770 | } | 831 | } |
@@ -791,11 +852,13 @@ void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) { | |||
791 | (!value && win.isMaximized())) | 852 | (!value && win.isMaximized())) |
792 | win.maximizeVertical(); | 853 | win.maximizeVertical(); |
793 | } else if (state == m_net_wm_state_fullscreen) { // fullscreen | 854 | } else if (state == m_net_wm_state_fullscreen) { // fullscreen |
855 | if ((value && !win.isFullscreen()) || | ||
856 | (!value && win.isFullscreen())) | ||
794 | setFullscreen(win, value); | 857 | setFullscreen(win, value); |
795 | } else if (state == m_net_wm_state_hidden || | 858 | } else if (state == m_net_wm_state_hidden || |
796 | state == m_net_wm_state_skip_taskbar) { | 859 | state == m_net_wm_state_skip_taskbar) { |
797 | win.setFocusHidden(value); | 860 | win.setFocusHidden(value); |
798 | win.setIconHidden(win.isFocusHidden()); | 861 | win.setIconHidden(value); |
799 | } else if (state == m_net_wm_state_below) { // bottom layer | 862 | } else if (state == m_net_wm_state_below) { // bottom layer |
800 | if (value) | 863 | if (value) |
801 | win.moveToLayer(Fluxbox::instance()->getBottomLayer()); | 864 | win.moveToLayer(Fluxbox::instance()->getBottomLayer()); |