diff options
Diffstat (limited to 'src/Ewmh.cc')
-rw-r--r-- | src/Ewmh.cc | 149 |
1 files changed, 121 insertions, 28 deletions
diff --git a/src/Ewmh.cc b/src/Ewmh.cc index fc762e7..6f12ab7 100644 --- a/src/Ewmh.cc +++ b/src/Ewmh.cc | |||
@@ -28,6 +28,8 @@ | |||
28 | #include "WinClient.hh" | 28 | #include "WinClient.hh" |
29 | #include "Workspace.hh" | 29 | #include "Workspace.hh" |
30 | #include "Layer.hh" | 30 | #include "Layer.hh" |
31 | #include "WinClientUtil.hh" | ||
32 | |||
31 | #include "FbTk/App.hh" | 33 | #include "FbTk/App.hh" |
32 | #include "FbTk/FbWindow.hh" | 34 | #include "FbTk/FbWindow.hh" |
33 | #include "FbTk/I18n.hh" | 35 | #include "FbTk/I18n.hh" |
@@ -109,11 +111,28 @@ void Ewmh::initForScreen(BScreen &screen) { | |||
109 | m_net_wm_state_fullscreen, | 111 | m_net_wm_state_fullscreen, |
110 | m_net_wm_state_hidden, | 112 | m_net_wm_state_hidden, |
111 | m_net_wm_state_skip_taskbar, | 113 | m_net_wm_state_skip_taskbar, |
112 | 114 | m_net_wm_state_modal, | |
115 | m_net_wm_state_below, | ||
116 | m_net_wm_state_above, | ||
117 | |||
113 | // window type | 118 | // window type |
114 | m_net_wm_window_type, | 119 | m_net_wm_window_type, |
115 | m_net_wm_window_type_dock, | 120 | m_net_wm_window_type_dock, |
116 | m_net_wm_window_type_desktop, | 121 | m_net_wm_window_type_desktop, |
122 | m_net_wm_window_type_splash, | ||
123 | |||
124 | // window actions | ||
125 | m_net_wm_allowed_actions, | ||
126 | m_net_wm_action_move, | ||
127 | m_net_wm_action_resize, | ||
128 | m_net_wm_action_minimize, | ||
129 | m_net_wm_action_shade, | ||
130 | m_net_wm_action_stick, | ||
131 | m_net_wm_action_maximize_horz, | ||
132 | m_net_wm_action_maximize_vert, | ||
133 | m_net_wm_action_fullscreen, | ||
134 | m_net_wm_action_change_desktop, | ||
135 | m_net_wm_action_close, | ||
117 | 136 | ||
118 | // root properties | 137 | // root properties |
119 | m_net_client_list, | 138 | m_net_client_list, |
@@ -223,6 +242,15 @@ void Ewmh::setupFrame(FluxboxWindow &win) { | |||
223 | win.setMovable(false); | 242 | win.setMovable(false); |
224 | win.setResizable(false); | 243 | win.setResizable(false); |
225 | win.stick(); | 244 | win.stick(); |
245 | |||
246 | } else if (atoms[l] == m_net_wm_window_type_splash) { | ||
247 | /* | ||
248 | * _NET_WM_WINDOW_TYPE_SPLASH indicates that the | ||
249 | * window is a splash screen displayed as an application | ||
250 | * is starting up. | ||
251 | */ | ||
252 | win.setDecoration(FluxboxWindow::DECOR_NONE); | ||
253 | win.setMovable(false); | ||
226 | } | 254 | } |
227 | 255 | ||
228 | } | 256 | } |
@@ -297,7 +325,8 @@ void Ewmh::updateClientList(BScreen &screen) { | |||
297 | Window *wl = FB_new_nothrow Window[num]; | 325 | Window *wl = FB_new_nothrow Window[num]; |
298 | if (wl == 0) { | 326 | if (wl == 0) { |
299 | _FB_USES_NLS; | 327 | _FB_USES_NLS; |
300 | cerr<<_FBTEXT(Ewmh, OutOfMemoryClientList, "Fatal: Out of memory, can't allocate for EWMH client list", "")<<endl; | 328 | cerr<<_FBTEXT(Ewmh, OutOfMemoryClientList, |
329 | "Fatal: Out of memory, can't allocate for EWMH client list", "")<<endl; | ||
301 | return; | 330 | return; |
302 | } | 331 | } |
303 | 332 | ||
@@ -523,8 +552,8 @@ void Ewmh::updateWorkarea(BScreen &screen) { | |||
523 | 552 | ||
524 | void Ewmh::updateState(FluxboxWindow &win) { | 553 | void Ewmh::updateState(FluxboxWindow &win) { |
525 | 554 | ||
526 | // TODO: should we update the _NET_WM_ALLOWED_ACTIONS | 555 | |
527 | // here too? | 556 | updateActions(win); |
528 | 557 | ||
529 | typedef std::vector<unsigned int> StateVec; | 558 | typedef std::vector<unsigned int> StateVec; |
530 | 559 | ||
@@ -542,14 +571,13 @@ void Ewmh::updateState(FluxboxWindow &win) { | |||
542 | state.push_back(m_net_wm_state_hidden); | 571 | state.push_back(m_net_wm_state_hidden); |
543 | if (win.isIconHidden()) | 572 | if (win.isIconHidden()) |
544 | state.push_back(m_net_wm_state_skip_taskbar); | 573 | state.push_back(m_net_wm_state_skip_taskbar); |
545 | if (win.isFullscreen()) { | 574 | if (win.isFullscreen()) |
546 | state.push_back(m_net_wm_state_fullscreen); | 575 | state.push_back(m_net_wm_state_fullscreen); |
547 | } | 576 | if (win.winClient().isModal()) |
577 | state.push_back(m_net_wm_state_modal); | ||
548 | 578 | ||
549 | FluxboxWindow::ClientList::iterator it = win.clientList().begin(); | 579 | FluxboxWindow::ClientList::iterator it = win.clientList().begin(); |
550 | FluxboxWindow::ClientList::iterator it_end = win.clientList().end(); | 580 | FluxboxWindow::ClientList::iterator it_end = win.clientList().end(); |
551 | |||
552 | it = win.clientList().begin(); | ||
553 | for (; it != it_end; ++it) { | 581 | for (; it != it_end; ++it) { |
554 | 582 | ||
555 | // search the old states for _NET_WM_STATE_SKIP_PAGER and append it | 583 | // search the old states for _NET_WM_STATE_SKIP_PAGER and append it |
@@ -565,18 +593,19 @@ void Ewmh::updateState(FluxboxWindow &win) { | |||
565 | &data); | 593 | &data); |
566 | if (data) { | 594 | if (data) { |
567 | Atom *old_states = (Atom *)data; | 595 | Atom *old_states = (Atom *)data; |
568 | for (unsigned long i=0; i < nitems; ++i) | 596 | for (unsigned long i=0; i < nitems; ++i) { |
569 | if (old_states[i] == m_net_wm_state_skip_pager) { | 597 | if (old_states[i] == m_net_wm_state_skip_pager) { |
570 | client_state.push_back(m_net_wm_state_skip_pager); | 598 | client_state.push_back(m_net_wm_state_skip_pager); |
571 | } | 599 | } |
600 | } | ||
572 | XFree(data); | 601 | XFree(data); |
573 | } | 602 | } |
574 | 603 | ||
575 | if (!client_state.empty()) | 604 | if (!client_state.empty()) { |
576 | (*it)->changeProperty(m_net_wm_state, XA_ATOM, 32, PropModeReplace, | 605 | (*it)->changeProperty(m_net_wm_state, XA_ATOM, 32, PropModeReplace, |
577 | reinterpret_cast<unsigned char*>(&client_state.front()), | 606 | reinterpret_cast<unsigned char*>(&client_state.front()), |
578 | client_state.size()); | 607 | client_state.size()); |
579 | else | 608 | } else |
580 | (*it)->deleteProperty(m_net_wm_state); | 609 | (*it)->deleteProperty(m_net_wm_state); |
581 | } | 610 | } |
582 | } | 611 | } |
@@ -750,9 +779,6 @@ bool Ewmh::checkClientMessage(const XClientMessageEvent &ce, | |||
750 | 779 | ||
751 | bool Ewmh::propertyNotify(WinClient &winclient, Atom the_property) { | 780 | bool Ewmh::propertyNotify(WinClient &winclient, Atom the_property) { |
752 | if (the_property == m_net_wm_strut) { | 781 | if (the_property == m_net_wm_strut) { |
753 | #ifdef DEBUG | ||
754 | cerr<<"_NET_WM_STRUT"<<endl; | ||
755 | #endif // DEBUG | ||
756 | updateStrut(winclient); | 782 | updateStrut(winclient); |
757 | return true; | 783 | return true; |
758 | } | 784 | } |
@@ -791,6 +817,7 @@ void Ewmh::createAtoms() { | |||
791 | m_net_wm_window_type = XInternAtom(disp, "_NET_WM_WINDOW_TYPE", False); | 817 | m_net_wm_window_type = XInternAtom(disp, "_NET_WM_WINDOW_TYPE", False); |
792 | m_net_wm_window_type_dock = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_DOCK", False); | 818 | m_net_wm_window_type_dock = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_DOCK", False); |
793 | m_net_wm_window_type_desktop = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_DESKTOP", False); | 819 | m_net_wm_window_type_desktop = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_DESKTOP", False); |
820 | m_net_wm_window_type_splash = XInternAtom(disp, "_NET_WM_WINDOW_TYPE_SPLASH", False); | ||
794 | 821 | ||
795 | // state atom and the supported state atoms | 822 | // state atom and the supported state atoms |
796 | m_net_wm_state = XInternAtom(disp, "_NET_WM_STATE", False); | 823 | m_net_wm_state = XInternAtom(disp, "_NET_WM_STATE", False); |
@@ -804,19 +831,20 @@ void Ewmh::createAtoms() { | |||
804 | m_net_wm_state_skip_pager = XInternAtom(disp, "_NET_WM_STATE_SKIP_PAGER", False); | 831 | m_net_wm_state_skip_pager = XInternAtom(disp, "_NET_WM_STATE_SKIP_PAGER", False); |
805 | m_net_wm_state_above = XInternAtom(disp, "_NET_WM_STATE_ABOVE", False); | 832 | m_net_wm_state_above = XInternAtom(disp, "_NET_WM_STATE_ABOVE", False); |
806 | m_net_wm_state_below = XInternAtom(disp, "_NET_WM_STATE_BELOW", False); | 833 | m_net_wm_state_below = XInternAtom(disp, "_NET_WM_STATE_BELOW", False); |
834 | m_net_wm_state_modal = XInternAtom(disp, "_NET_WM_STATE_MODAL", False); | ||
807 | 835 | ||
808 | // allowed actions | 836 | // allowed actions |
809 | m_net_wm_allowed_actions = XInternAtom(disp, "_NET_WM_ALLOWED_ACTIONS", False); | 837 | m_net_wm_allowed_actions = XInternAtom(disp, "_NET_WM_ALLOWED_ACTIONS", False); |
810 | m_net_wm_action_move = XInternAtom(disp, "_NET_WM_ACTIONS_MOVE", False); | 838 | m_net_wm_action_move = XInternAtom(disp, "_NET_WM_ACTION_MOVE", False); |
811 | m_net_wm_action_resize = XInternAtom(disp, "_NET_WM_ACTIONS_RESIZE", False); | 839 | m_net_wm_action_resize = XInternAtom(disp, "_NET_WM_ACTION_RESIZE", False); |
812 | m_net_wm_action_minimize = XInternAtom(disp, "_NET_WM_ACTIONS_MINIMIZE", False); | 840 | m_net_wm_action_minimize = XInternAtom(disp, "_NET_WM_ACTION_MINIMIZE", False); |
813 | m_net_wm_action_shade = XInternAtom(disp, "_NET_WM_ACTIONS_SHADE", False); | 841 | m_net_wm_action_shade = XInternAtom(disp, "_NET_WM_ACTION_SHADE", False); |
814 | m_net_wm_action_stick = XInternAtom(disp, "_NET_WM_ACTIONS_STICK", False); | 842 | m_net_wm_action_stick = XInternAtom(disp, "_NET_WM_ACTION_STICK", False); |
815 | m_net_wm_action_maximize_horz = XInternAtom(disp, "_NET_WM_ACTIONS_MAXIMIZE_HORZ", False); | 843 | m_net_wm_action_maximize_horz = XInternAtom(disp, "_NET_WM_ACTION_MAXIMIZE_HORZ", False); |
816 | m_net_wm_action_maximize_vert = XInternAtom(disp, "_NET_WM_ACTIONS_MAXIMIZE_VERT", False); | 844 | m_net_wm_action_maximize_vert = XInternAtom(disp, "_NET_WM_ACTION_MAXIMIZE_VERT", False); |
817 | m_net_wm_action_fullscreen = XInternAtom(disp, "_NET_WM_ACTIONS_FULLSCREEN", False); | 845 | m_net_wm_action_fullscreen = XInternAtom(disp, "_NET_WM_ACTION_FULLSCREEN", False); |
818 | m_net_wm_action_change_desktop = XInternAtom(disp, "_NET_WM_ACTIONS_CHANGE_DESKTOP", False); | 846 | m_net_wm_action_change_desktop = XInternAtom(disp, "_NET_WM_ACTION_CHANGE_DESKTOP", False); |
819 | m_net_wm_action_close = XInternAtom(disp, "_NET_WM_ACTIONS_CLOSE", False); | 847 | m_net_wm_action_close = XInternAtom(disp, "_NET_WM_ACTION_CLOSE", False); |
820 | 848 | ||
821 | m_net_wm_strut = XInternAtom(disp, "_NET_WM_STRUT", False); | 849 | m_net_wm_strut = XInternAtom(disp, "_NET_WM_STRUT", False); |
822 | m_net_wm_icon_geometry = XInternAtom(disp, "_NET_WM_ICON_GEOMETRY", False); | 850 | m_net_wm_icon_geometry = XInternAtom(disp, "_NET_WM_ICON_GEOMETRY", False); |
@@ -890,7 +918,7 @@ void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) { | |||
890 | win.iconify(); | 918 | win.iconify(); |
891 | else if (!value && win.isIconic()) | 919 | else if (!value && win.isIconic()) |
892 | win.deiconify(); | 920 | win.deiconify(); |
893 | } else if (state == m_net_wm_state_skip_taskbar) { | 921 | } else if (state == m_net_wm_state_skip_taskbar) { // skip taskbar |
894 | win.setIconHidden(value); | 922 | win.setIconHidden(value); |
895 | } else if (state == m_net_wm_state_below) { // bottom layer | 923 | } else if (state == m_net_wm_state_below) { // bottom layer |
896 | if (value) | 924 | if (value) |
@@ -904,13 +932,14 @@ void Ewmh::setState(FluxboxWindow &win, Atom state, bool value) { | |||
904 | else | 932 | else |
905 | win.moveToLayer(Layer::NORMAL); | 933 | win.moveToLayer(Layer::NORMAL); |
906 | } | 934 | } |
935 | // Note: state == net_wm_state_modal, We should not change it | ||
907 | } | 936 | } |
908 | 937 | ||
909 | // toggle window state | 938 | // toggle window state |
910 | void Ewmh::toggleState(FluxboxWindow &win, Atom state) { | 939 | void Ewmh::toggleState(FluxboxWindow &win, Atom state) { |
911 | if (state == m_net_wm_state_sticky) { | 940 | if (state == m_net_wm_state_sticky) { // sticky |
912 | win.stick(); | 941 | win.stick(); |
913 | } else if (state == m_net_wm_state_shaded){ | 942 | } else if (state == m_net_wm_state_shaded){ // shaded |
914 | win.shade(); | 943 | win.shade(); |
915 | } else if (state == m_net_wm_state_maximized_horz ) { // maximized Horizontal | 944 | } else if (state == m_net_wm_state_maximized_horz ) { // maximized Horizontal |
916 | win.maximizeHorizontal(); | 945 | win.maximizeHorizontal(); |
@@ -923,7 +952,7 @@ void Ewmh::toggleState(FluxboxWindow &win, Atom state) { | |||
923 | win.deiconify(); | 952 | win.deiconify(); |
924 | else | 953 | else |
925 | win.iconify(); | 954 | win.iconify(); |
926 | } else if (state == m_net_wm_state_skip_taskbar) { | 955 | } else if (state == m_net_wm_state_skip_taskbar) { // taskbar |
927 | win.setIconHidden(!win.isIconHidden()); | 956 | win.setIconHidden(!win.isIconHidden()); |
928 | } else if (state == m_net_wm_state_below) { // bottom layer | 957 | } else if (state == m_net_wm_state_below) { // bottom layer |
929 | if (win.layerNum() == Layer::BOTTOM) | 958 | if (win.layerNum() == Layer::BOTTOM) |
@@ -958,6 +987,70 @@ void Ewmh::updateStrut(WinClient &winclient) { | |||
958 | } | 987 | } |
959 | } | 988 | } |
960 | 989 | ||
990 | void Ewmh::updateActions(FluxboxWindow &win) { | ||
991 | |||
992 | /* From Extended Window Manager Hints, draft 1.3: | ||
993 | * | ||
994 | * _NET_WM_ALLOWED_ACTIONS, ATOM[] | ||
995 | * | ||
996 | * A list of atoms indicating user operations that the | ||
997 | * Window Manager supports for this window. Atoms present in the | ||
998 | * list indicate allowed actions, atoms not present in the list | ||
999 | * indicate actions that are not supported for this window. The | ||
1000 | * Window Manager MUST keep this property updated to reflect the | ||
1001 | * actions which are currently "active" or "sensitive" for a window. | ||
1002 | * Taskbars, Pagers, and other tools use _NET_WM_ALLOWED_ACTIONS to | ||
1003 | * decide which actions should be made available to the user. | ||
1004 | */ | ||
1005 | |||
1006 | typedef std::vector<Atom> ActionsVector; | ||
1007 | ActionsVector actions; | ||
1008 | actions.reserve(10); | ||
1009 | // all windows can change desktop, | ||
1010 | // be shaded or be sticky | ||
1011 | actions.push_back(m_net_wm_action_change_desktop); | ||
1012 | actions.push_back(m_net_wm_action_shade); | ||
1013 | actions.push_back(m_net_wm_action_stick); | ||
1014 | |||
1015 | if (win.isResizable()) | ||
1016 | actions.push_back(m_net_wm_action_resize); | ||
1017 | if (win.isMoveable()) | ||
1018 | actions.push_back(m_net_wm_action_move); | ||
1019 | if (win.isClosable()) | ||
1020 | actions.push_back(m_net_wm_action_close); | ||
1021 | if (win.isIconifiable()) | ||
1022 | actions.push_back(m_net_wm_action_minimize); | ||
1023 | |||
1024 | unsigned int max_width, max_height; | ||
1025 | WinClientUtil::maxSize(win.clientList(), max_width, max_height); | ||
1026 | |||
1027 | // if unlimited max width we can maximize horizontal | ||
1028 | if (max_width == 0) { | ||
1029 | actions.push_back(m_net_wm_action_maximize_horz); | ||
1030 | } | ||
1031 | // if unlimited max height we can maxmize vert | ||
1032 | if (max_height == 0) { | ||
1033 | actions.push_back(m_net_wm_action_maximize_vert); | ||
1034 | } | ||
1035 | |||
1036 | // if we have unlimited size in all directions we can have this window | ||
1037 | // in fullscreen mode | ||
1038 | if (max_height == 0 && max_width == 0) { | ||
1039 | actions.push_back(m_net_wm_action_fullscreen); | ||
1040 | } | ||
1041 | |||
1042 | |||
1043 | |||
1044 | FluxboxWindow::ClientList::iterator it = win.clientList().begin(); | ||
1045 | FluxboxWindow::ClientList::iterator it_end = win.clientList().end(); | ||
1046 | for (; it != it_end; ++it) { | ||
1047 | (*it)->changeProperty(m_net_wm_allowed_actions, XA_ATOM, 32, PropModeReplace, | ||
1048 | reinterpret_cast<unsigned char*>(&actions.front()), | ||
1049 | actions.size()); | ||
1050 | } | ||
1051 | |||
1052 | } | ||
1053 | |||
961 | void Ewmh::setupState(FluxboxWindow &win) { | 1054 | void Ewmh::setupState(FluxboxWindow &win) { |
962 | /* From Extended Window Manager Hints, draft 1.3: | 1055 | /* From Extended Window Manager Hints, draft 1.3: |
963 | * | 1056 | * |