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