1 #ifndef YCLIENT_H
2 #define YCLIENT_H
3 
4 #include "ywindow.h"
5 #include "ymenu.h"
6 #include "MwmUtil.h"
7 #ifndef InputHint
8 #include <X11/Xutil.h>
9 #endif
10 
11 #define InvalidFrameState   (-1)
12 
13 class YFrameWindow;
14 class WindowListItem;
15 class YIcon;
16 
17 typedef int FrameState;
18 
19 enum WindowType {
20     wtCombo,
21     wtDesktop,
22     wtDialog,
23     wtDND,
24     wtDock,
25     wtDropdownMenu,
26     wtMenu,
27     wtNormal,
28     wtNotification,
29     wtPopupMenu,
30     wtSplash,
31     wtToolbar,
32     wtTooltip,
33     wtUtility,
34 };
35 
36 class ClassHint : public XClassHint {
37 public:
ClassHint()38     ClassHint() { res_name = res_class = nullptr; }
ClassHint(const char * name,const char * klas)39     ClassHint(const char* name, const char* klas) { init(name, klas); }
ClassHint(const ClassHint & ch)40     ClassHint(const ClassHint& ch) { init(ch.res_name, ch.res_class); }
~ClassHint()41     ~ClassHint() { reset(); }
init(const char * name,const char * klas)42     void init(const char* name, const char* klas) {
43         res_name = name ? strdup(name) : nullptr;
44         res_class = klas ? strdup(klas) : nullptr;
45     }
reset()46     void reset() {
47         if (res_name) { XFree(res_name); res_name = nullptr; }
48         if (res_class) { XFree(res_class); res_class = nullptr; }
49     }
50     bool match(const char* resource) const;
51     char* resource() const;
52     void operator=(const ClassHint& hint) {
53         if (this != &hint) {
54             reset();
55             init(hint.res_name, hint.res_class);
56         }
57     }
58     bool operator==(const ClassHint& hint) {
59         return ((res_name && hint.res_name) ?
60                 !strcmp(res_name, hint.res_name) :
61                 res_name == hint.res_name) &&
62                ((res_class && hint.res_class) ?
63                 !strcmp(res_class, hint.res_class) :
64                 res_class == hint.res_class);
65     }
66     bool operator!=(const ClassHint& hint) {
67         return !operator==(hint);
68     }
nonempty()69     bool nonempty() {
70         return ::nonempty(res_name) || ::nonempty(res_class);
71     }
72 };
73 
74 /*
75  * X11 time state to support _NET_WM_USER_TIME.
76  * Keep track of the time in seconds when we receive a X11 time stamp.
77  * Only compare two X11 time stamps if they are in a time interval.
78  */
79 class UserTime {
80 private:
81     unsigned long xtime;
82     bool valid;
83     unsigned long since;
84     enum : unsigned long {
85         XTimeMask = 0xFFFFFFFFUL,       // milliseconds
86         XTimeRange = 0x7FFFFFFFUL,      // milliseconds
87         SInterval = 0x3FFFFFFFUL / 1000,     // seconds
88     };
89 public:
UserTime()90     UserTime() : xtime(0), valid(false), since(0) { }
91     explicit UserTime(unsigned long xtime, bool valid = true) :
xtime(xtime & XTimeMask)92         xtime(xtime & XTimeMask), valid(valid), since(seconds()) { }
time()93     unsigned long time() const { return xtime; }
good()94     bool good() const { return valid; }
when()95     long when() const { return since; }
96     bool update(unsigned long xtime, bool valid = true) {
97         UserTime u(xtime, valid);
98         return *this < u || xtime == 0 ? (*this = u, true) : false;
99     }
100     bool operator<(const UserTime& u) const {
101         if (since == 0 || u.since == 0) return u.since != 0;
102         if (valid == false || u.valid == false) return u.valid;
103         if (since < u.since && u.since - since > SInterval) return true;
104         if (since > u.since && since - u.since > SInterval) return false;
105         if (xtime < u.xtime) return u.xtime - xtime <= XTimeRange;
106         if (xtime > u.xtime) return xtime - u.xtime >  XTimeRange;
107         return false;
108     }
109     bool operator==(const UserTime& u) const {
110         return !(*this < u) && !(u < *this);
111     }
112 };
113 
114 class ClientData {
115 public:
116     virtual void setWinListItem(WindowListItem *i) = 0;
117     virtual YFrameWindow *owner() const = 0;
118     virtual ref<YIcon> getIcon() const = 0;
119     virtual mstring getTitle() const = 0;
120     virtual mstring getIconTitle() const = 0;
121     virtual void activateWindow(bool raise, bool curWork) = 0;
122     virtual bool isHidden() const = 0;
123     virtual bool isMaximized() const = 0;
124     virtual bool isMaximizedVert() const = 0;
125     virtual bool isMaximizedHoriz() const = 0;
126     virtual bool isMaximizedFully() const = 0;
127     virtual bool isMinimized() const = 0;
128     virtual bool isFullscreen() const = 0;
129     virtual bool isRollup() const = 0;
130     virtual void actionPerformed(YAction action, unsigned int modifiers = 0) = 0;
131     virtual bool focused() const = 0;
132     virtual bool visibleNow() const = 0;
133     virtual bool canClose() const = 0;
134     virtual bool canShow() const = 0;
135     virtual bool canHide() const = 0;
136     virtual bool canLower() const = 0;
137     virtual bool canMinimize() const = 0;
138     virtual bool canMaximize() const = 0;
139     virtual bool canRaise() const = 0;
140     virtual bool canRestore() const = 0;
141     virtual bool canRollup() const = 0;
142     virtual void wmRaise() = 0;
143     virtual void wmLower() = 0;
144     virtual void wmMinimize() = 0;
145     virtual int getWorkspace() const = 0;
146     virtual int getTrayOrder() const = 0;
147     virtual int getTrayOption() const = 0;
148     virtual unsigned frameOptions() const = 0;
149     virtual bool isSticky() const = 0;
150     virtual bool isAllWorkspaces() const = 0;
151     virtual bool startMinimized() const = 0;
152     virtual void wmOccupyWorkspace(int workspace) = 0;
153     virtual void popupSystemMenu(YWindow *owner) = 0;
154     virtual void popupSystemMenu(YWindow *owner, int x, int y,
155                          unsigned int flags,
156                          YWindow *forWindow = nullptr) = 0;
157     virtual void updateSubmenus() = 0;
158     virtual Time since() const = 0;
159     virtual ClassHint* classHint() const = 0;
160     virtual Window clientLeader() const = 0;
161     virtual bool isUrgent() const = 0;
162     virtual void updateAppStatus() = 0;
163     virtual void removeAppStatus() = 0;
164 protected:
~ClientData()165     virtual ~ClientData() {}
166 };
167 
168 class YFrameClient: public YDndWindow
169                   , public YTimerListener
170 {
171     typedef YDndWindow super;
172 public:
173     YFrameClient(YWindow *parent, YFrameWindow *frame, Window win = 0,
174                  int depth = 0, Visual *visual = nullptr, Colormap cmap = 0);
175     virtual ~YFrameClient();
176 
177     virtual void handleProperty(const XPropertyEvent &property);
178     virtual void handleColormap(const XColormapEvent &colormap);
179     virtual void handleMapNotify(const XMapEvent& map);
180     virtual void handleUnmap(const XUnmapEvent &unmap);
181     virtual void handleDestroyWindow(const XDestroyWindowEvent &destroyWindow);
182     virtual void handleClientMessage(const XClientMessageEvent &message);
183 #ifdef CONFIG_SHAPE
184     virtual void handleShapeNotify(const XShapeEvent &shape);
185 #endif
186 
getBorder()187     int getBorder() const { return fBorder; }
setBorder(unsigned int border)188     void setBorder(unsigned int border) { fBorder = border; }
189     void setFrame(YFrameWindow *newFrame);
getFrame()190     YFrameWindow *getFrame() const { return fFrame; };
191 
192     enum WindowProtocols {
193         wpDeleteWindow = 1 << 0,
194         wpTakeFocus    = 1 << 1,
195         wpPing         = 1 << 2,
196     };
197 
protocol(WindowProtocols wp)198     bool protocol(WindowProtocols wp) const { return bool(fProtocols & wp); }
199     void sendMessage(Atom msg, Time ts, long p2 = 0L, long p3 = 0L, long p4 = 0L);
200     void sendTakeFocus();
201     void sendDelete();
202     void sendPing();
203     void recvPing(const XClientMessageEvent &message);
204     bool killPid();
timedOut()205     bool timedOut() const { return fTimedOut; }
206 
207     enum {
208         csKeepX = 1,
209         csKeepY = 2,
210         csRound = 4
211     };
212 
213     void constrainSize(int &w, int &h, int flags);
214 
215     void gravityOffsets(int &xp, int &yp);
216 
colormap()217     Colormap colormap() const { return fColormap; }
218     void setColormap(Colormap cmap);
219 
220     FrameState getFrameState();
221     void setFrameState(FrameState state);
222 
223     void getWMHints();
hints()224     XWMHints *hints() const { return fHints; }
wmHint(int flag)225     bool wmHint(int flag) const { return fHints && (fHints->flags & flag); }
226     Window windowGroupHint() const;
227     Window iconWindowHint() const;
228     Pixmap iconPixmapHint() const;
229     Pixmap iconMaskHint() const;
urgencyHint()230     bool urgencyHint() const { return wmHint(XUrgencyHint); }
231     bool isDockApp() const;
232     bool isDockAppIcon() const;
233     bool isDockAppWindow() const;
isDocked()234     bool isDocked() const { return fDocked; }
setDocked(bool docked)235     void setDocked(bool docked) { fDocked = docked; }
236 
237     void getSizeHints();
sizeHints()238     XSizeHints *sizeHints() const { return fSizeHints; }
sizeHintsFlags()239     int sizeHintsFlags() const { return fSizeHints ? int(fSizeHints->flags) : 0; }
winGravity()240     int winGravity() const { return hasbit(sizeHintsFlags(), PWinGravity)
241                                   ? fSizeHints->win_gravity : NorthWestGravity; }
242 
243     void getProtocols(bool force);
244 
245     void getTransient();
ownerWindow()246     Window ownerWindow() const { return fTransientFor; }
247 
248     void getClassHint();
classHint()249     ClassHint* classHint() { return &fClassHint; }
250 
251     void getNameHint();
252     void getNetWmName();
253     void getIconNameHint();
254     void getNetWmIconName();
255     void setWindowTitle(const char *title);
256     void setIconTitle(const char *title);
windowTitle()257     mstring windowTitle() { return fWindowTitle; }
iconTitle()258     mstring iconTitle() { return fIconTitle; }
259 
260     void setWorkspaceHint(int workspace);
261     bool getWinWorkspaceHint(int* workspace);
262 
263     void setLayerHint(int layer);
264     bool getLayerHint(int* layer);
265 
266     void setWinTrayHint(int tray_opt);
267     bool getWinTrayHint(int* tray_opt);
268 
269     void setStateHint();
270     void setWinHintsHint(int hints);
winHints()271     int winHints() const { return fWinHints; }
272 
273     bool getWinIcons(Atom* type, long* count, long** elem);
274     bool getKwmIcon(long* count, Pixmap** pixmap);
275     bool getNetWMIcon(long* count, long** elem);
276 
277     bool getNetWMStateHint(int* mask, int* state);
278     bool getNetWMDesktopHint(int* workspace);
279     bool getNetWMPid(long *pid);
280     bool getNetWMStrut(int *left, int *right, int *top, int *bottom);
281     bool getNetWMStrutPartial(int *left, int *right, int *top, int *bottom);
282     bool getNetStartupId(unsigned long &time);
283     bool getNetWMUserTime(Window window, unsigned long &time);
284     bool getNetWMUserTimeWindow(Window &window);
285     bool getNetWMWindowOpacity(long &opacity);
286     bool getNetWMWindowType(WindowType *window_type);
287     void setNetWMFullscreenMonitors(int top, int bottom, int left, int right);
288     void setNetFrameExtents(int left, int right, int top, int bottom);
289     void setNetWMAllowedActions(Atom *actions, int count);
290     void netStateRequest(int action, int mask);
291     void actionPerformed(YAction action);
292 
isPinging()293     bool isPinging() const { return fPinging; }
pingTime()294     bool pingTime() const { return fPingTime; }
295     virtual bool handleTimer(YTimer *t);
296 
mwmHints()297     MwmHints *mwmHints() const { return fMwmHints._ptr(); }
298     void getMwmHints();
299     void setMwmHints(const MwmHints &mwm);
300     long mwmFunctions();
301     long mwmDecors();
302 
shaped()303     bool shaped() const { return fShaped; }
304     void queryShape();
305 
306     void getClientLeader();
307     void getWindowRole();
308 
clientLeader()309     Window clientLeader() const { return fClientLeader; }
windowRole()310     mstring windowRole() const { return fWindowRole; }
311 
312     mstring getClientId(Window leader);
313     void getPropertiesList();
314 
315     // virtual void configure(const YRect2 &rect);
316     virtual void handleGravityNotify(const XGravityEvent &gravity);
317 
isKdeTrayWindow()318     bool isKdeTrayWindow() { return prop.kde_net_wm_system_tray_window_for; }
319 
isEmbed()320     bool isEmbed() { return prop.xembed_info; }
321 
322 private:
323     YFrameWindow *fFrame;
324     int fProtocols;
325     int haveButtonGrab;
326     unsigned int fBorder;
327     FrameState fSavedFrameState;
328     int fWinStateHint;
329     XSizeHints *fSizeHints;
330     ClassHint fClassHint;
331     XWMHints *fHints;
332     Colormap fColormap;
333     bool fDocked;
334     bool fShaped;
335     bool fTimedOut;
336     bool fPinging;
337     long fPingTime;
338     lazy<YTimer> fPingTimer;
339     int fWinHints;
340     long fPid;
341 
342     mstring fWindowTitle;
343     mstring fIconTitle;
344 
345     Window fClientLeader;
346     mstring fWMWindowRole;
347     mstring fWindowRole;
348 
349     lazy<MwmHints> fMwmHints;
350 
351     Window fTransientFor;
352 
353     Pixmap *kwmIcons;
354     struct {
355         bool wm_state : 1; // no property notify
356         bool wm_hints : 1;
357         bool wm_normal_hints : 1;
358         bool wm_transient_for : 1;
359         bool wm_name : 1;
360         bool wm_icon_name : 1;
361         bool wm_class : 1;
362         bool wm_protocols : 1;
363         bool wm_client_leader : 1;
364         bool wm_window_role : 1;
365         bool window_role : 1;
366         bool sm_client_id : 1;
367         bool kwm_win_icon : 1;
368         bool kde_net_wm_system_tray_window_for : 1;
369         bool net_wm_name : 1;
370         bool net_wm_icon_name : 1;
371         bool net_wm_icon : 1;
372         bool net_wm_strut : 1;
373         bool net_wm_strut_partial : 1;
374         bool net_wm_desktop : 1; // no property notify
375         bool net_wm_state : 1; // no property notify
376         bool net_wm_window_type : 1;
377         bool net_startup_id : 1; // no property notify
378         bool net_wm_user_time : 1;
379         bool net_wm_user_time_window : 1;
380         bool net_wm_window_opacity : 1;
381         bool net_wm_pid : 1;
382         bool mwm_hints : 1;
383         bool win_tray : 1; // no property notify
384         bool win_layer : 1; // no property notify
385         bool win_icons : 1;
386         bool xembed_info : 1;
387     } prop;
388 private: // not-used
389     YFrameClient(const YFrameClient &);
390     YFrameClient &operator=(const YFrameClient &);
391 };
392 
393 #endif // YCLIENT_H
394 
395 // vim: set sw=4 ts=4 et:
396