LeechCraft  %{LEECHCRAFT_VERSION}
Modular cross-platform feature rich live environment.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
xwrapper.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * LeechCraft - modular cross-platform feature rich internet client.
3  * Copyright (C) 2006-2014 Georg Rudoy
4  *
5  * Boost Software License - Version 1.0 - August 17th, 2003
6  *
7  * Permission is hereby granted, free of charge, to any person or organization
8  * obtaining a copy of the software and accompanying documentation covered by
9  * this license (the "Software") to use, reproduce, display, distribute,
10  * execute, and transmit the Software, and to prepare derivative works of the
11  * Software, and to permit third-parties to whom the Software is furnished to
12  * do so, all subject to the following:
13  *
14  * The copyright notices in the Software and this entire statement, including
15  * the above license grant, this restriction and the following disclaimer,
16  * must be included in all copies of the Software, in whole or in part, and
17  * all derivative works of the Software, unless such copies or derivative
18  * works are solely in the form of machine-executable object code generated by
19  * a source language processor.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  **********************************************************************/
29 
30 #include "xwrapper.h"
31 #include <limits>
32 #include <type_traits>
33 #include <QString>
34 #include <QPixmap>
35 #include <QIcon>
36 #include <QApplication>
37 #include <QWidget>
38 #include <QDesktopWidget>
39 #include <QAbstractEventDispatcher>
40 #include <QtDebug>
41 #include <QTimer>
42 #include <X11/Xlib.h>
43 #include <X11/Xutil.h>
44 #include <X11/Xatom.h>
45 
46 namespace LeechCraft
47 {
48 namespace Util
49 {
50  const int SourcePager = 2;
51 
52  const int StateRemove = 0;
53  const int StateAdd = 1;
54 
55  namespace
56  {
57  bool EvFilter (void *msg)
58  {
59  return XWrapper::Instance ().Filter (static_cast<XEvent*> (msg));
60  }
61  }
62 
63  XWrapper::XWrapper ()
64  : Display_ (QX11Info::display ())
65  , AppWin_ (QX11Info::appRootWindow ())
66  , PrevFilter_ (QAbstractEventDispatcher::instance ()->setEventFilter (EvFilter))
67  {
68  XSelectInput (Display_,
69  AppWin_,
70  PropertyChangeMask | StructureNotifyMask | SubstructureNotifyMask);
71  }
72 
73  XWrapper& XWrapper::Instance ()
74  {
75  static XWrapper w;
76  return w;
77  }
78 
79  Display* XWrapper::GetDisplay () const
80  {
81  return Display_;
82  }
83 
84  Window XWrapper::GetRootWindow () const
85  {
86  return AppWin_;
87  }
88 
89  bool XWrapper::Filter (XEvent *ev)
90  {
91  if (ev->type == PropertyNotify)
92  HandlePropNotify (&ev->xproperty);
93 
94  return PrevFilter_ ? PrevFilter_ (ev) : false;
95  }
96 
97  namespace
98  {
99  template<typename T>
100  struct IsDoublePtr : std::false_type {};
101 
102  template<typename T>
103  struct IsDoublePtr<T**> : std::true_type {};
104 
105  template<typename T>
106  class Guarded
107  {
108  T *Data_;
109  public:
110  Guarded ()
111  : Data_ { nullptr }
112  {
113  }
114 
115  ~Guarded ()
116  {
117  if (Data_)
118  XFree (Data_);
119  }
120 
121  T** Get (bool clear = true)
122  {
123  if (clear && Data_)
124  XFree (Data_);
125  return &Data_;
126  }
127 
128  template<typename U>
129  U GetAs (bool clear = true)
130  {
131  if (clear && Data_)
132  XFree (Data_);
133  return IsDoublePtr<U>::value ?
134  reinterpret_cast<U> (&Data_) :
135  reinterpret_cast<U> (Data_);
136  }
137 
138  T operator[] (size_t idx) const
139  {
140  return Data_ [idx];
141  }
142 
143  T& operator[] (size_t idx)
144  {
145  return Data_ [idx];
146  }
147 
148  operator bool () const
149  {
150  return Data_ != nullptr;
151  }
152 
153  bool operator! () const
154  {
155  return !Data_;
156  }
157  };
158  }
159 
160  void XWrapper::Sync ()
161  {
162  XFlush (Display_);
163  XSync (Display_, False);
164  }
165 
166  QList<Window> XWrapper::GetWindows ()
167  {
168  ulong length = 0;
169  Guarded<Window> data;
170 
171  QList<Window> result;
172  if (GetRootWinProp (GetAtom ("_NET_CLIENT_LIST"), &length, data.GetAs<uchar**> ()))
173  for (ulong i = 0; i < length; ++i)
174  result << data [i];
175  return result;
176  }
177 
178  QString XWrapper::GetWindowTitle (Window wid)
179  {
180  QString name;
181 
182  ulong length = 0;
183  Guarded<uchar> data;
184 
185  auto utf8Str = GetAtom ("UTF8_STRING");
186 
187  if (GetWinProp (wid, GetAtom ("_NET_WM_VISIBLE_NAME"), &length, data.Get (), utf8Str))
188  name = QString::fromUtf8 (data.GetAs<char*> (false));
189 
190  if (name.isEmpty ())
191  if (GetWinProp (wid, GetAtom ("_NET_WM_NAME"), &length, data.Get (), utf8Str))
192  name = QString::fromUtf8 (data.GetAs<char*> (false));
193 
194  if (name.isEmpty ())
195  if (GetWinProp (wid, GetAtom ("XA_WM_NAME"), &length, data.Get (), XA_STRING))
196  name = QString::fromUtf8 (data.GetAs<char*> (false));
197 
198  if (name.isEmpty ())
199  {
200  XFetchName (Display_, wid, data.GetAs<char**> ());
201  name = QString (data.GetAs<char*> (false));
202  }
203 
204  if (name.isEmpty ())
205  {
206  XTextProperty prop;
207  if (XGetWMName (Display_, wid, &prop))
208  {
209  name = QString::fromUtf8 (reinterpret_cast<char*> (prop.value));
210  XFree (prop.value);
211  }
212  }
213 
214  return name;
215  }
216 
217  QIcon XWrapper::GetWindowIcon (Window wid)
218  {
219  int fmt = 0;
220  ulong type, count, extra;
221  Guarded<ulong> data;
222 
223  XGetWindowProperty (Display_, wid, GetAtom ("_NET_WM_ICON"),
224  0, std::numeric_limits<long>::max (), False, AnyPropertyType,
225  &type, &fmt, &count, &extra,
226  data.GetAs<uchar**> ());
227 
228  if (!data)
229  return {};
230 
231  QIcon icon;
232 
233  auto cur = *data.Get (false);
234  auto end = cur + count;
235  while (cur < end)
236  {
237  QImage img (cur [0], cur [1], QImage::Format_ARGB32);
238  cur += 2;
239  for (int i = 0; i < img.byteCount () / 4; ++i, ++cur)
240  reinterpret_cast<uint*> (img.bits ()) [i] = *cur;
241 
242  icon.addPixmap (QPixmap::fromImage (img));
243  }
244 
245  return icon;
246  }
247 
248  WinStateFlags XWrapper::GetWindowState (Window wid)
249  {
250  WinStateFlags result;
251 
252  ulong length = 0;
253  ulong *data = 0;
254  if (!GetWinProp (wid, GetAtom ("_NET_WM_STATE"),
255  &length, reinterpret_cast<uchar**> (&data), XA_ATOM))
256  return result;
257 
258  for (ulong i = 0; i < length; ++i)
259  {
260  const auto curAtom = data [i];
261 
262  auto set = [this, &curAtom, &result] (const QString& atom, WinStateFlag flag)
263  {
264  if (curAtom == GetAtom ("_NET_WM_STATE_" + atom))
265  result |= flag;
266  };
267 
268  set ("MODAL", WinStateFlag::Modal);
269  set ("STICKY", WinStateFlag::Sticky);
270  set ("MAXIMIZED_VERT", WinStateFlag::MaximizedVert);
271  set ("MAXIMIZED_HORZ", WinStateFlag::MaximizedHorz);
272  set ("SHADED", WinStateFlag::Shaded);
273  set ("SKIP_TASKBAR", WinStateFlag::SkipTaskbar);
274  set ("SKIP_PAGER", WinStateFlag::SkipPager);
275  set ("HIDDEN", WinStateFlag::Hidden);
276  set ("FULLSCREEN", WinStateFlag::Fullscreen);
277  set ("ABOVE", WinStateFlag::OnTop);
278  set ("BELOW", WinStateFlag::OnBottom);
279  set ("DEMANDS_ATTENTION", WinStateFlag::Attention);
280  }
281 
282  XFree (data);
283 
284  return result;
285  }
286 
287  AllowedActionFlags XWrapper::GetWindowActions (Window wid)
288  {
289  AllowedActionFlags result;
290 
291  ulong length = 0;
292  ulong *data = 0;
293  if (!GetWinProp (wid, GetAtom ("_NET_WM_ALLOWED_ACTIONS"),
294  &length, reinterpret_cast<uchar**> (&data), XA_ATOM))
295  return result;
296 
297  for (ulong i = 0; i < length; ++i)
298  {
299  const auto curAtom = data [i];
300 
301  auto set = [this, &curAtom, &result] (const QString& atom, AllowedActionFlag flag)
302  {
303  if (curAtom == GetAtom ("_NET_WM_ACTION_" + atom))
304  result |= flag;
305  };
306 
307  set ("MOVE", AllowedActionFlag::Move);
308  set ("RESIZE", AllowedActionFlag::Resize);
309  set ("MINIMIZE", AllowedActionFlag::Minimize);
310  set ("SHADE", AllowedActionFlag::Shade);
311  set ("STICK", AllowedActionFlag::Stick);
312  set ("MAXIMIZE_HORZ", AllowedActionFlag::MaximizeHorz);
313  set ("MAXIMIZE_VERT", AllowedActionFlag::MaximizeVert);
314  set ("FULLSCREEN", AllowedActionFlag::ShowFullscreen);
315  set ("CHANGE_DESKTOP", AllowedActionFlag::ChangeDesktop);
316  set ("CLOSE", AllowedActionFlag::Close);
317  set ("ABOVE", AllowedActionFlag::MoveToTop);
318  set ("BELOW", AllowedActionFlag::MoveToBottom);
319  }
320 
321  XFree (data);
322 
323  return result;
324  }
325 
326  Window XWrapper::GetActiveApp ()
327  {
328  auto win = GetActiveWindow ();
329  if (!win)
330  return 0;
331 
332  Window transient = None;
333  if (!ShouldShow (win) && XGetTransientForHint (Display_, win, &transient))
334  return transient;
335 
336  return win;
337  }
338 
339  bool XWrapper::IsLCWindow (Window wid)
340  {
341  ulong length = 0;
342  Guarded<uchar> data;
343  if (GetWinProp (wid, GetAtom ("WM_CLASS"), &length, data.Get ()) &&
344  QString (data.GetAs<char*> (false)) == "leechcraft")
345  return true;
346 
347  return false;
348  }
349 
350  bool XWrapper::ShouldShow (Window wid)
351  {
352  const QList<Atom> ignoreAtoms
353  {
354  GetAtom ("_NET_WM_WINDOW_TYPE_DESKTOP"),
355  GetAtom ("_NET_WM_WINDOW_TYPE_DOCK"),
356  GetAtom ("_NET_WM_WINDOW_TYPE_TOOLBAR"),
357  GetAtom ("_NET_WM_WINDOW_TYPE_UTILITY"),
358  GetAtom ("_NET_WM_WINDOW_TYPE_MENU"),
359  GetAtom ("_NET_WM_WINDOW_TYPE_SPLASH"),
360  GetAtom ("_NET_WM_WINDOW_TYPE_POPUP_MENU")
361  };
362 
363  for (const auto& type : GetWindowType (wid))
364  if (ignoreAtoms.contains (type))
365  return false;
366 
367  if (GetWindowState (wid) & WinStateFlag::SkipTaskbar)
368  return false;
369 
370  Window transient = None;
371  if (!XGetTransientForHint (Display_, wid, &transient))
372  return true;
373 
374  if (transient == 0 || transient == wid || transient == AppWin_)
375  return true;
376 
377  return !GetWindowType (transient).contains (GetAtom ("_NET_WM_WINDOW_TYPE_NORMAL"));
378  }
379 
380  void XWrapper::Subscribe (Window wid)
381  {
382  if (IsLCWindow (wid))
383  return;
384 
385  XSelectInput (Display_, wid, PropertyChangeMask);
386  }
387 
388  void XWrapper::SetStrut (QWidget *widget, Qt::ToolBarArea area)
389  {
390  const auto wid = widget->effectiveWinId ();
391 
392  const auto& winGeom = widget->geometry ();
393 
394  switch (area)
395  {
396  case Qt::BottomToolBarArea:
397  SetStrut (wid,
398  0, 0, 0, winGeom.height (),
399  0, 0,
400  0, 0,
401  0, 0,
402  winGeom.left (), winGeom.right ());
403  break;
404  case Qt::TopToolBarArea:
405  SetStrut (wid,
406  0, 0, winGeom.height (), 0,
407  0, 0,
408  0, 0,
409  winGeom.left (), winGeom.right (),
410  0, 0);
411  break;
412  case Qt::LeftToolBarArea:
413  SetStrut (wid,
414  winGeom.width (), 0, 0, 0,
415  winGeom.top (), winGeom.bottom (),
416  0, 0,
417  0, 0,
418  0, 0);
419  break;
420  case Qt::RightToolBarArea:
421  SetStrut (wid,
422  0, winGeom.width (), 0, 0,
423  0, 0,
424  winGeom.top (), winGeom.bottom (),
425  0, 0,
426  0, 0);
427  break;
428  default:
429  qWarning () << Q_FUNC_INFO
430  << "incorrect area passed"
431  << area;
432  break;
433  }
434  }
435 
436  void XWrapper::ClearStrut (QWidget *w)
437  {
438  const auto wid = w->effectiveWinId ();
439  XDeleteProperty (Display_, wid, GetAtom ("_NET_WM_STRUT"));
440  XDeleteProperty (Display_, wid, GetAtom ("_NET_WM_STRUT_PARTIAL"));
441  }
442 
443  void XWrapper::SetStrut (Window wid,
444  int left, int right, int top, int bottom,
445  int leftStartY, int leftEndY,
446  int rightStartY, int rightEndY,
447  int topStartX, int topEndX,
448  int bottomStartX, int bottomEndX)
449  {
450  ulong struts[12] = { 0 };
451 
452  struts [0] = left;
453  struts [1] = right;
454  struts [2] = top;
455  struts [3] = bottom;
456 
457  struts [4] = leftStartY;
458  struts [5] = leftEndY;
459  struts [6] = rightStartY;
460  struts [7] = rightEndY;
461  struts [8] = topStartX;
462  struts [9] = topEndX;
463  struts [10] = bottomStartX;
464  struts [11] = bottomEndX;
465 
466  XChangeProperty (Display_, wid, GetAtom ("_NET_WM_STRUT_PARTIAL"),
467  XA_CARDINAL, 32, PropModeReplace, reinterpret_cast<uchar*> (struts), 12);
468 
469  XChangeProperty (Display_, wid, GetAtom ("_NET_WM_STRUT"),
470  XA_CARDINAL, 32, PropModeReplace, reinterpret_cast<uchar*> (struts), 4);
471  }
472 
473  void XWrapper::RaiseWindow (Window wid)
474  {
475  SendMessage (wid, GetAtom ("_NET_ACTIVE_WINDOW"), SourcePager);
476  }
477 
478  void XWrapper::MinimizeWindow (Window wid)
479  {
480  SendMessage (wid, GetAtom ("WM_CHANGE_STATE"), IconicState);
481  }
482 
483  void XWrapper::MaximizeWindow (Window wid)
484  {
485  SendMessage (wid, GetAtom ("_NET_WM_STATE"), StateAdd,
486  GetAtom ("_NET_WM_STATE_MAXIMIZED_VERT"),
487  GetAtom ("_NET_WM_STATE_MAXIMIZED_HORZ"),
488  SourcePager);
489  }
490 
491  void XWrapper::UnmaximizeWindow (Window wid)
492  {
493  SendMessage (wid, GetAtom ("_NET_WM_STATE"), StateRemove,
494  GetAtom ("_NET_WM_STATE_MAXIMIZED_VERT"),
495  GetAtom ("_NET_WM_STATE_MAXIMIZED_HORZ"),
496  SourcePager);
497  }
498 
499  void XWrapper::ResizeWindow (Window wid, int width, int height)
500  {
501  XResizeWindow (Display_, wid, width, height);
502  }
503 
504  void XWrapper::ShadeWindow (Window wid)
505  {
506  SendMessage (wid, GetAtom ("_NET_WM_STATE"),
507  StateAdd, GetAtom ("_NET_WM_STATE_SHADED"), 0, SourcePager);
508  }
509 
510  void XWrapper::UnshadeWindow (Window wid)
511  {
512  SendMessage (wid, GetAtom ("_NET_WM_STATE"),
513  StateRemove, GetAtom ("_NET_WM_STATE_SHADED"), 0, SourcePager);
514  }
515 
516  void XWrapper::MoveWindowTo (Window wid, Layer layer)
517  {
518  const auto top = layer == Layer::Top ? StateAdd : StateRemove;
519  const auto bottom = layer == Layer::Bottom ? StateAdd : StateRemove;
520 
521  SendMessage (wid, GetAtom ("_NET_WM_STATE"), top,
522  GetAtom ("_NET_WM_STATE_ABOVE"), 0, SourcePager);
523 
524  SendMessage (wid, GetAtom ("_NET_WM_STATE"), bottom,
525  GetAtom ("_NET_WM_STATE_BELOW"), 0, SourcePager);
526  }
527 
528  void XWrapper::CloseWindow (Window wid)
529  {
530  SendMessage (wid, GetAtom ("_NET_CLOSE_WINDOW"), 0, SourcePager);
531  }
532 
533  template<typename T>
534  void XWrapper::HandlePropNotify (T ev)
535  {
536  if (ev->state == PropertyDelete)
537  return;
538 
539  const auto wid = ev->window;
540 
541  if (wid == AppWin_)
542  {
543  if (ev->atom == GetAtom ("_NET_CLIENT_LIST"))
544  emit windowListChanged ();
545  else if (ev->atom == GetAtom ("_NET_ACTIVE_WINDOW"))
546  emit activeWindowChanged ();
547  else if (ev->atom == GetAtom ("_NET_CURRENT_DESKTOP"))
548  emit desktopChanged ();
549  }
550  else
551  {
552  if (ev->atom == GetAtom ("_NET_WM_VISIBLE_NAME") ||
553  ev->atom == GetAtom ("WM_NAME"))
554  emit windowNameChanged (wid);
555  else if (ev->atom == GetAtom ("_NET_WM_ICON"))
556  emit windowIconChanged (wid);
557  else if (ev->atom == GetAtom ("_NET_WM_DESKTOP"))
558  emit windowDesktopChanged (wid);
559  else if (ev->atom == GetAtom ("_NET_WM_STATE"))
560  emit windowStateChanged (wid);
561  else if (ev->atom == GetAtom ("_NET_WM_ALLOWED_ACTIONS"))
562  emit windowActionsChanged (wid);
563  }
564  }
565 
566  Window XWrapper::GetActiveWindow ()
567  {
568  ulong length = 0;
569  Guarded<ulong> data;
570 
571  if (!GetRootWinProp (GetAtom ("_NET_ACTIVE_WINDOW"), &length, data.GetAs<uchar**> (), XA_WINDOW))
572  return 0;
573 
574  if (!length)
575  return 0;
576 
577  return data [0];
578  }
579 
580  int XWrapper::GetDesktopCount ()
581  {
582  ulong length = 0;
583  Guarded<ulong> data;
584 
585  if (GetRootWinProp (GetAtom ("_NET_NUMBER_OF_DESKTOPS"), &length, data.GetAs<uchar**> (), XA_CARDINAL))
586  return length > 0 ? data [0] : -1;
587 
588  return -1;
589  }
590 
591  int XWrapper::GetCurrentDesktop ()
592  {
593  ulong length = 0;
594  Guarded<ulong> data;
595 
596  if (GetRootWinProp (GetAtom ("_NET_CURRENT_DESKTOP"), &length, data.GetAs<uchar**> (), XA_CARDINAL))
597  return length > 0 ? data [0] : -1;
598 
599  return -1;
600  }
601 
602  void XWrapper::SetCurrentDesktop (int desktop)
603  {
604  SendMessage (AppWin_, GetAtom ("_NET_CURRENT_DESKTOP"), desktop);
605  }
606 
607  QStringList XWrapper::GetDesktopNames ()
608  {
609  ulong length = 0;
610  Guarded<uchar> data;
611 
612  if (!GetRootWinProp (GetAtom ("_NET_DESKTOP_NAMES"),
613  &length, data.GetAs<uchar**> (), GetAtom ("UTF8_STRING")))
614  return {};
615 
616  if (!data)
617  return {};
618 
619  QStringList result;
620  for (char *pos = data.GetAs<char*> (false), *end = data.GetAs<char*> (false) + length; pos < end; )
621  {
622  const auto& str = QString::fromUtf8 (pos);
623  result << str;
624  pos += str.toUtf8 ().size () + 1;
625  }
626  return result;
627  }
628 
629  QString XWrapper::GetDesktopName (int desktop, const QString& def)
630  {
631  return GetDesktopNames ().value (desktop, def);
632  }
633 
634  int XWrapper::GetWindowDesktop (Window wid)
635  {
636  ulong length = 0;
637  Guarded<ulong> data;
638  if (GetWinProp (wid, GetAtom ("_NET_WM_DESKTOP"), &length, data.GetAs<uchar**> (), XA_CARDINAL) && length)
639  return data [0];
640 
641  if (GetWinProp (wid, GetAtom ("_WIN_WORKSPACE"), &length, data.GetAs<uchar**> (), XA_CARDINAL) && length)
642  return data [0];
643 
644  return -1;
645  }
646 
647  void XWrapper::MoveWindowToDesktop (Window wid, int num)
648  {
649  SendMessage (wid, GetAtom ("_NET_WM_DESKTOP"), num);
650  }
651 
652  QRect XWrapper::GetAvailableGeometry (int screen)
653  {
654  auto dw = QApplication::desktop ();
655 
656  if (screen < 0 || screen >= dw->screenCount ())
657  screen = dw->primaryScreen ();
658 
659  if (dw->isVirtualDesktop ())
660  screen = DefaultScreen (Display_);
661 
662  auto available = dw->screenGeometry (screen);
663  const auto deskGeom = dw->rect ();
664 
665  for (const auto wid : GetWindows ())
666  {
667  ulong length = 0;
668  Guarded<ulong> struts;
669  const auto status = GetWinProp (wid, GetAtom ("_NET_WM_STRUT_PARTIAL"),
670  &length, struts.GetAs<uchar**> (), XA_CARDINAL);
671  if (!status || length != 12)
672  continue;
673 
674  const QRect left
675  {
676  static_cast<int> (deskGeom.x ()),
677  static_cast<int> (deskGeom.y () + struts [4]),
678  static_cast<int> (struts [0]),
679  static_cast<int> (struts [5] - struts [4])
680  };
681  if (available.intersects (left))
682  available.setX (left.width ());
683 
684  const QRect right
685  {
686  static_cast<int> (deskGeom.x () + deskGeom.width () - struts [1]),
687  static_cast<int> (deskGeom.y () + struts [6]),
688  static_cast<int> (struts [1]),
689  static_cast<int> (struts [7] - struts [6])
690  };
691  if (available.intersects (right))
692  available.setWidth (right.x () - available.x ());
693 
694  const QRect top
695  {
696  static_cast<int> (deskGeom.x () + struts [8]),
697  static_cast<int> (deskGeom.y ()),
698  static_cast<int> (struts [9] - struts [8]),
699  static_cast<int> (struts [2])
700  };
701  if (available.intersects (top))
702  available.setY (top.height ());
703 
704  const QRect bottom
705  {
706  static_cast<int> (deskGeom.x () + struts [10]),
707  static_cast<int> (deskGeom.y () + deskGeom.height () - struts [3]),
708  static_cast<int> (struts [11] - struts [10]),
709  static_cast<int> (struts [3])
710  };
711  if (available.intersects (bottom))
712  available.setHeight (bottom.y () - available.y ());
713  }
714 
715  return available;
716  }
717 
718  QRect XWrapper::GetAvailableGeometry (QWidget *widget)
719  {
720  return GetAvailableGeometry (QApplication::desktop ()->screenNumber (widget));
721  }
722 
723  Atom XWrapper::GetAtom (const QString& name)
724  {
725  if (Atoms_.contains (name))
726  return Atoms_ [name];
727 
728  auto atom = XInternAtom (Display_, name.toLocal8Bit (), false);
729  Atoms_ [name] = atom;
730  return atom;
731  }
732 
733  bool XWrapper::GetWinProp (Window win, Atom property,
734  ulong *length, unsigned char **result, Atom req) const
735  {
736  int fmt = 0;
737  ulong type = 0, rest = 0;
738  return XGetWindowProperty (Display_, win,
739  property, 0, 1024, false, req, &type,
740  &fmt, length, &rest, result) == Success;
741  }
742 
743  bool XWrapper::GetRootWinProp (Atom property,
744  ulong *length, uchar **result, Atom req) const
745  {
746  return GetWinProp (AppWin_, property, length, result, req);
747  }
748 
749  QList<Atom> XWrapper::GetWindowType (Window wid)
750  {
751  QList<Atom> result;
752 
753  ulong length = 0;
754  ulong *data = nullptr;
755 
756  if (!GetWinProp (wid, GetAtom ("_NET_WM_WINDOW_TYPE"),
757  &length, reinterpret_cast<uchar**> (&data)))
758  return result;
759 
760  for (ulong i = 0; i < length; ++i)
761  result << data [i];
762 
763  XFree (data);
764  return result;
765  }
766 
767  bool XWrapper::SendMessage (Window wid, Atom atom, ulong d0, ulong d1, ulong d2, ulong d3, ulong d4)
768  {
769  XClientMessageEvent msg;
770  msg.window = wid;
771  msg.type = ClientMessage;
772  msg.message_type = atom;
773  msg.send_event = true;
774  msg.display = Display_;
775  msg.format = 32;
776  msg.data.l [0] = d0;
777  msg.data.l [1] = d1;
778  msg.data.l [2] = d2;
779  msg.data.l [3] = d3;
780  msg.data.l [4] = d4;
781 
782  return XSendEvent (Display_, AppWin_, FALSE, SubstructureRedirectMask | SubstructureNotifyMask,
783  reinterpret_cast<XEvent*> (&msg)) == Success;
784  }
785 
786  void XWrapper::initialize ()
787  {
788  }
789 }
790 }
static XWrapper & Instance()
Definition: xwrapper.cpp:73
union _XEvent XEvent
Definition: xwrapper.h:48
const int StateRemove
Definition: xwrapper.cpp:52
const int StateAdd
Definition: xwrapper.cpp:53
T * Data_
Definition: xwrapper.cpp:108
QWidget * Display_
Definition: util.cpp:85
const int SourcePager
Definition: xwrapper.cpp:50
No type (item doesn't correspond to a radio station).
unsigned long Window
Definition: xwrapper.h:43
bool Filter(XEvent *)
Definition: xwrapper.cpp:89