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