aboutsummaryrefslogtreecommitdiff
path: root/src/Ewmh.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ewmh.cc')
-rw-r--r--src/Ewmh.cc149
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
524void Ewmh::updateState(FluxboxWindow &win) { 553void 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
751bool Ewmh::propertyNotify(WinClient &winclient, Atom the_property) { 780bool 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
910void Ewmh::toggleState(FluxboxWindow &win, Atom state) { 939void 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
990void 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
961void Ewmh::setupState(FluxboxWindow &win) { 1054void Ewmh::setupState(FluxboxWindow &win) {
962 /* From Extended Window Manager Hints, draft 1.3: 1055 /* From Extended Window Manager Hints, draft 1.3:
963 * 1056 *