1 //
2 // X11Util.cc for pekwm
3 // Copyright (C) 2021 Claes Nästén <pekdon@gmail.com>
4 //
5 // This program is licensed under the GNU GPL.
6 // See the LICENSE file for more information.
7 //
8
9 #include "PWinObj.hh"
10 #include "X11Util.hh"
11 #include "Util.hh"
12
NetWMStates(void)13 NetWMStates::NetWMStates(void)
14 : modal(false),
15 sticky(false),
16 max_vert(false),
17 max_horz(false), shaded(false),
18 skip_taskbar(false),
19 skip_pager(false),
20 hidden(false),
21 fullscreen(false),
22 above(false),
23 below(false),
24 demands_attention(false)
25 {
26 }
27
~NetWMStates(void)28 NetWMStates::~NetWMStates(void)
29 {
30 }
31
32 namespace X11Util {
33
34 /**
35 * Get geometry for the given head, -1 will return the screen
36 * geometry.
37 */
getHeadGeometry(int head)38 Geometry getHeadGeometry(int head)
39 {
40 if (head < 0) {
41 return X11::getScreenGeometry();
42 }
43 return X11::getHeadGeometry(head);
44 }
45
46 /**
47 * Get current head, depending on configuration it is the same
48 * head as the cursor is on OR the head where the focused window
49 * is on.
50 */
getCurrHead(CurrHeadSelector chs)51 uint getCurrHead(CurrHeadSelector chs)
52 {
53 PWinObj *wo;
54 switch (chs) {
55 case CURR_HEAD_SELECTOR_FOCUSED_WINDOW:
56 wo = PWinObj::getFocusedPWinObj();
57 if (wo != nullptr) {
58 return X11::getNearestHead(wo->getX() + (wo->getWidth() / 2),
59 wo->getY() + (wo->getHeight() / 2));
60 }
61 case CURR_HEAD_SELECTOR_CURSOR:
62 case CURR_HEAD_SELECTOR_NO:
63 return X11::getCursorHead();
64 }
65
66 return 0;
67 }
68
69 /**
70 * Get head closest to center of provided PWinObj.
71 */
getNearestHead(const PWinObj & wo)72 uint getNearestHead(const PWinObj& wo)
73 {
74 return X11::getNearestHead(wo.getX() + (wo.getWidth() / 2),
75 wo.getY() + (wo.getHeight() / 2));
76 }
77
78 /**
79 * Grabs the button button, with the mod mod and mask mask on the
80 * window win and cursor curs with "all" possible extra modifiers
81 */
82 void
grabButton(int button,int mod,int mask,Window win,int mode)83 grabButton(int button, int mod, int mask, Window win, int mode)
84 {
85 uint num_lock = X11::getNumLock();
86 uint scroll_lock = X11::getScrollLock();
87
88 X11::grabButton(button, mod, win, mask, mode);
89 X11::grabButton(button, mod|LockMask, win, mask, mode);
90
91 if (num_lock) {
92 X11::grabButton(button, mod|num_lock, win, mask, mode);
93 X11::grabButton(button, mod|num_lock|LockMask, win, mask, mode);
94 }
95 if (scroll_lock) {
96 X11::grabButton(button, mod|scroll_lock, win, mask, mode);
97 X11::grabButton(button, mod|scroll_lock|LockMask, win, mask, mode);
98 }
99 if (num_lock && scroll_lock) {
100 X11::grabButton(button, mod|num_lock|scroll_lock, win, mask, mode);
101 X11::grabButton(button, mod|num_lock|scroll_lock|LockMask,
102 win, mask, mode);
103 }
104 }
105
106 /**
107 * Reads MWM hints from a client.
108 *
109 * @return true if the hint was read succesfully.
110 */
111 bool
readMwmHints(Window win,MwmHints & hints)112 readMwmHints(Window win, MwmHints &hints)
113 {
114 Atom atom = X11::getAtom(MOTIF_WM_HINTS);
115 uchar *data;
116 ulong items_read;
117 if (! X11::getProperty(win, atom, atom, 20L, &data, &items_read)) {
118 return false;
119 }
120
121 if (items_read >= MWM_HINTS_NUM) {
122 hints = *reinterpret_cast<MwmHints*>(data);
123 }
124
125 X11::free(data);
126 return items_read >= MWM_HINTS_NUM;
127 }
128
129 /**
130 * Read EWMH state atoms on window.
131 */
132 bool
readEwmhStates(Window win,NetWMStates & win_states)133 readEwmhStates(Window win, NetWMStates &win_states)
134 {
135 int num = 0;
136 Atom *states = static_cast<Atom*>(X11::getEwmhPropData(win, STATE,
137 XA_ATOM, num));
138 if (! states) {
139 return false;
140 }
141
142 for (int i = 0; i < num; ++i) {
143 if (states[i] == X11::getAtom(STATE_MODAL)) {
144 win_states.modal = true;
145 } else if (states[i] == X11::getAtom(STATE_STICKY)) {
146 win_states.sticky = true;
147 } else if (states[i] == X11::getAtom(STATE_MAXIMIZED_VERT)) {
148 win_states.max_vert = true;
149 } else if (states[i] == X11::getAtom(STATE_MAXIMIZED_HORZ)) {
150 win_states.max_horz = true;
151 } else if (states[i] == X11::getAtom(STATE_SHADED)) {
152 win_states.shaded = true;
153 } else if (states[i] == X11::getAtom(STATE_SKIP_TASKBAR)) {
154 win_states.skip_taskbar = true;
155 } else if (states[i] == X11::getAtom(STATE_SKIP_PAGER)) {
156 win_states.skip_pager = true;
157 } else if (states[i] == X11::getAtom(STATE_DEMANDS_ATTENTION)) {
158 win_states.demands_attention = true;
159 } else if (states[i] == X11::getAtom(STATE_HIDDEN)) {
160 win_states.hidden = true;
161 } else if (states[i] == X11::getAtom(STATE_FULLSCREEN)) {
162 win_states.fullscreen = true;
163 } else if (states[i] == X11::getAtom(STATE_ABOVE)) {
164 win_states.above = true;
165 } else if (states[i] == X11::getAtom(STATE_BELOW)) {
166 win_states.below = true;
167 }
168 }
169
170 X11::free(states);
171
172 return true;
173 }
174
175 }
176
177 #ifndef PEKWM_HAVE_XUTF8
178
179 void
Xutf8SetWMProperties(Display * dpy,Window win,const char * window_name,const char * icon_name,char ** argv,int argc,XSizeHints * normal_hints,XWMHints * wm_hints,XClassHint * class_hints)180 Xutf8SetWMProperties(Display *dpy, Window win,
181 const char* window_name, const char* icon_name,
182 char** argv, int argc,
183 XSizeHints* normal_hints, XWMHints* wm_hints,
184 XClassHint* class_hints)
185 {
186 X11::setUtf8String(win, WM_CLIENT_MACHINE, Util::getHostname());
187 X11::setUtf8String(win, WM_NAME, window_name);
188 X11::setUtf8String(win, WM_ICON_NAME, icon_name);
189
190 if (normal_hints) {
191 XSetNormalHints(dpy, win, normal_hints);
192 }
193 if (wm_hints) {
194 XSetWMHints(dpy, win, wm_hints);
195 }
196 if (class_hints) {
197 XSetClassHint(dpy, win, class_hints);
198 }
199 }
200
201 #endif // PEKWM_HAVE_XUTF8
202