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