LeechCraft  0.6.70-10870-g558588d6ec
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 <QTimer>
42 #include <X11/Xlib.h>
43 #include <X11/Xutil.h>
44 #include <X11/Xatom.h>
45 #include <xcb/xcb.h>
46 
47 namespace LeechCraft
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  for (int i = 0; i < img.byteCount () / 4; ++i, ++cur)
243  reinterpret_cast<uint*> (img.bits ()) [i] = *cur;
244 
245  icon.addPixmap (QPixmap::fromImage (img));
246  }
247 
248  return icon;
249  }
250 
251  WinStateFlags XWrapper::GetWindowState (Window wid)
252  {
253  WinStateFlags result;
254 
255  ulong length = 0;
256  ulong *data = 0;
257  if (!GetWinProp (wid, GetAtom ("_NET_WM_STATE"),
258  &length, reinterpret_cast<uchar**> (&data), XA_ATOM))
259  return result;
260 
261  for (ulong i = 0; i < length; ++i)
262  {
263  const auto curAtom = data [i];
264 
265  auto set = [this, &curAtom, &result] (const QString& atom, WinStateFlag flag)
266  {
267  if (curAtom == GetAtom ("_NET_WM_STATE_" + atom))
268  result |= flag;
269  };
270 
271  set ("MODAL", WinStateFlag::Modal);
272  set ("STICKY", WinStateFlag::Sticky);
273  set ("MAXIMIZED_VERT", WinStateFlag::MaximizedVert);
274  set ("MAXIMIZED_HORZ", WinStateFlag::MaximizedHorz);
275  set ("SHADED", WinStateFlag::Shaded);
276  set ("SKIP_TASKBAR", WinStateFlag::SkipTaskbar);
277  set ("SKIP_PAGER", WinStateFlag::SkipPager);
278  set ("HIDDEN", WinStateFlag::Hidden);
279  set ("FULLSCREEN", WinStateFlag::Fullscreen);
280  set ("ABOVE", WinStateFlag::OnTop);
281  set ("BELOW", WinStateFlag::OnBottom);
282  set ("DEMANDS_ATTENTION", WinStateFlag::Attention);
283  }
284 
285  XFree (data);
286 
287  return result;
288  }
289 
290  AllowedActionFlags XWrapper::GetWindowActions (Window wid)
291  {
292  AllowedActionFlags result;
293 
294  ulong length = 0;
295  ulong *data = 0;
296  if (!GetWinProp (wid, GetAtom ("_NET_WM_ALLOWED_ACTIONS"),
297  &length, reinterpret_cast<uchar**> (&data), XA_ATOM))
298  return result;
299 
300  for (ulong i = 0; i < length; ++i)
301  {
302  const auto curAtom = data [i];
303 
304  auto set = [this, &curAtom, &result] (const QString& atom, AllowedActionFlag flag)
305  {
306  if (curAtom == GetAtom ("_NET_WM_ACTION_" + atom))
307  result |= flag;
308  };
309 
310  set ("MOVE", AllowedActionFlag::Move);
311  set ("RESIZE", AllowedActionFlag::Resize);
312  set ("MINIMIZE", AllowedActionFlag::Minimize);
313  set ("SHADE", AllowedActionFlag::Shade);
314  set ("STICK", AllowedActionFlag::Stick);
315  set ("MAXIMIZE_HORZ", AllowedActionFlag::MaximizeHorz);
316  set ("MAXIMIZE_VERT", AllowedActionFlag::MaximizeVert);
317  set ("FULLSCREEN", AllowedActionFlag::ShowFullscreen);
318  set ("CHANGE_DESKTOP", AllowedActionFlag::ChangeDesktop);
319  set ("CLOSE", AllowedActionFlag::Close);
320  set ("ABOVE", AllowedActionFlag::MoveToTop);
321  set ("BELOW", AllowedActionFlag::MoveToBottom);
322  }
323 
324  XFree (data);
325 
326  return result;
327  }
328 
329  Window XWrapper::GetActiveApp ()
330  {
331  auto win = GetActiveWindow ();
332  if (!win)
333  return 0;
334 
335  Window transient = None;
336  if (!ShouldShow (win) && XGetTransientForHint (Display_, win, &transient))
337  return transient;
338 
339  return win;
340  }
341 
342  bool XWrapper::IsLCWindow (Window wid)
343  {
344  ulong length = 0;
345  Guarded<uchar> data;
346  if (GetWinProp (wid, GetAtom ("WM_CLASS"), &length, data.Get ()) &&
347  QString (data.GetAs<char*> (false)).startsWith ("leechcraft"))
348  return true;
349 
350  return false;
351  }
352 
353  bool XWrapper::ShouldShow (Window wid)
354  {
355  const QList<Atom> ignoreAtoms
356  {
357  GetAtom ("_NET_WM_WINDOW_TYPE_DESKTOP"),
358  GetAtom ("_NET_WM_WINDOW_TYPE_DOCK"),
359  GetAtom ("_NET_WM_WINDOW_TYPE_TOOLBAR"),
360  GetAtom ("_NET_WM_WINDOW_TYPE_UTILITY"),
361  GetAtom ("_NET_WM_WINDOW_TYPE_MENU"),
362  GetAtom ("_NET_WM_WINDOW_TYPE_SPLASH"),
363  GetAtom ("_NET_WM_WINDOW_TYPE_POPUP_MENU")
364  };
365 
366  for (const auto& type : GetWindowType (wid))
367  if (ignoreAtoms.contains (type))
368  return false;
369 
370  if (GetWindowState (wid) & WinStateFlag::SkipTaskbar)
371  return false;
372 
373  Window transient = None;
374  if (!XGetTransientForHint (Display_, wid, &transient))
375  return true;
376 
377  if (transient == 0 || transient == wid || transient == AppWin_)
378  return true;
379 
380  return !GetWindowType (transient).contains (GetAtom ("_NET_WM_WINDOW_TYPE_NORMAL"));
381  }
382 
383  void XWrapper::Subscribe (Window wid)
384  {
385  if (IsLCWindow (wid))
386  return;
387 
388  XSelectInput (Display_, wid, PropertyChangeMask);
389  }
390 
391  void XWrapper::SetStrut (QWidget *widget, Qt::ToolBarArea area)
392  {
393  const auto wid = widget->effectiveWinId ();
394 
395  const auto& winGeom = widget->geometry ();
396 
397  switch (area)
398  {
399  case Qt::BottomToolBarArea:
400  SetStrut (wid,
401  0, 0, 0, winGeom.height (),
402  0, 0,
403  0, 0,
404  0, 0,
405  winGeom.left (), winGeom.right ());
406  break;
407  case Qt::TopToolBarArea:
408  SetStrut (wid,
409  0, 0, winGeom.height (), 0,
410  0, 0,
411  0, 0,
412  winGeom.left (), winGeom.right (),
413  0, 0);
414  break;
415  case Qt::LeftToolBarArea:
416  SetStrut (wid,
417  winGeom.width (), 0, 0, 0,
418  winGeom.top (), winGeom.bottom (),
419  0, 0,
420  0, 0,
421  0, 0);
422  break;
423  case Qt::RightToolBarArea:
424  SetStrut (wid,
425  0, winGeom.width (), 0, 0,
426  0, 0,
427  winGeom.top (), winGeom.bottom (),
428  0, 0,
429  0, 0);
430  break;
431  default:
432  qWarning () << Q_FUNC_INFO
433  << "incorrect area passed"
434  << area;
435  break;
436  }
437  }
438 
439  void XWrapper::ClearStrut (QWidget *w)
440  {
441  const auto wid = w->effectiveWinId ();
442  XDeleteProperty (Display_, wid, GetAtom ("_NET_WM_STRUT"));
443  XDeleteProperty (Display_, wid, GetAtom ("_NET_WM_STRUT_PARTIAL"));
444  }
445 
446  void XWrapper::SetStrut (Window wid,
447  int left, int right, int top, int bottom,
448  int leftStartY, int leftEndY,
449  int rightStartY, int rightEndY,
450  int topStartX, int topEndX,
451  int bottomStartX, int bottomEndX)
452  {
453  ulong struts[12] = { 0 };
454 
455  struts [0] = left;
456  struts [1] = right;
457  struts [2] = top;
458  struts [3] = bottom;
459 
460  struts [4] = leftStartY;
461  struts [5] = leftEndY;
462  struts [6] = rightStartY;
463  struts [7] = rightEndY;
464  struts [8] = topStartX;
465  struts [9] = topEndX;
466  struts [10] = bottomStartX;
467  struts [11] = bottomEndX;
468 
469  XChangeProperty (Display_, wid, GetAtom ("_NET_WM_STRUT_PARTIAL"),
470  XA_CARDINAL, 32, PropModeReplace, reinterpret_cast<uchar*> (struts), 12);
471 
472  XChangeProperty (Display_, wid, GetAtom ("_NET_WM_STRUT"),
473  XA_CARDINAL, 32, PropModeReplace, reinterpret_cast<uchar*> (struts), 4);
474  }
475 
476  void XWrapper::RaiseWindow (Window wid)
477  {
478  SendMessage (wid, GetAtom ("_NET_ACTIVE_WINDOW"), SourcePager);
479  }
480 
481  void XWrapper::MinimizeWindow (Window wid)
482  {
483  SendMessage (wid, GetAtom ("WM_CHANGE_STATE"), IconicState);
484  }
485 
486  void XWrapper::MaximizeWindow (Window wid)
487  {
488  SendMessage (wid, GetAtom ("_NET_WM_STATE"), StateAdd,
489  GetAtom ("_NET_WM_STATE_MAXIMIZED_VERT"),
490  GetAtom ("_NET_WM_STATE_MAXIMIZED_HORZ"),
491  SourcePager);
492  }
493 
494  void XWrapper::UnmaximizeWindow (Window wid)
495  {
496  SendMessage (wid, GetAtom ("_NET_WM_STATE"), StateRemove,
497  GetAtom ("_NET_WM_STATE_MAXIMIZED_VERT"),
498  GetAtom ("_NET_WM_STATE_MAXIMIZED_HORZ"),
499  SourcePager);
500  }
501 
502  void XWrapper::ResizeWindow (Window wid, int width, int height)
503  {
504  XResizeWindow (Display_, wid, width, height);
505  }
506 
507  void XWrapper::ShadeWindow (Window wid)
508  {
509  SendMessage (wid, GetAtom ("_NET_WM_STATE"),
510  StateAdd, GetAtom ("_NET_WM_STATE_SHADED"), 0, SourcePager);
511  }
512 
513  void XWrapper::UnshadeWindow (Window wid)
514  {
515  SendMessage (wid, GetAtom ("_NET_WM_STATE"),
516  StateRemove, GetAtom ("_NET_WM_STATE_SHADED"), 0, SourcePager);
517  }
518 
519  void XWrapper::MoveWindowTo (Window wid, Layer layer)
520  {
521  const auto top = layer == Layer::Top ? StateAdd : StateRemove;
522  const auto bottom = layer == Layer::Bottom ? StateAdd : StateRemove;
523 
524  SendMessage (wid, GetAtom ("_NET_WM_STATE"), top,
525  GetAtom ("_NET_WM_STATE_ABOVE"), 0, SourcePager);
526 
527  SendMessage (wid, GetAtom ("_NET_WM_STATE"), bottom,
528  GetAtom ("_NET_WM_STATE_BELOW"), 0, SourcePager);
529  }
530 
531  void XWrapper::CloseWindow (Window wid)
532  {
533  SendMessage (wid, GetAtom ("_NET_CLOSE_WINDOW"), 0, SourcePager);
534  }
535 
536  template<typename T>
537  void XWrapper::HandlePropNotify (T ev)
538  {
539  if (ev->state == XCB_PROPERTY_DELETE)
540  return;
541 
542  const auto wid = ev->window;
543 
544  if (wid == AppWin_)
545  {
546  if (ev->atom == GetAtom ("_NET_CLIENT_LIST"))
547  emit windowListChanged ();
548  else if (ev->atom == GetAtom ("_NET_ACTIVE_WINDOW"))
549  emit activeWindowChanged ();
550  else if (ev->atom == GetAtom ("_NET_CURRENT_DESKTOP"))
551  emit desktopChanged ();
552  }
553  else
554  {
555  if (ev->atom == GetAtom ("_NET_WM_VISIBLE_NAME") ||
556  ev->atom == GetAtom ("WM_NAME"))
557  emit windowNameChanged (wid);
558  else if (ev->atom == GetAtom ("_NET_WM_ICON"))
559  emit windowIconChanged (wid);
560  else if (ev->atom == GetAtom ("_NET_WM_DESKTOP"))
561  emit windowDesktopChanged (wid);
562  else if (ev->atom == GetAtom ("_NET_WM_STATE"))
563  emit windowStateChanged (wid);
564  else if (ev->atom == GetAtom ("_NET_WM_ALLOWED_ACTIONS"))
565  emit windowActionsChanged (wid);
566  }
567  }
568 
569  Window XWrapper::GetActiveWindow ()
570  {
571  ulong length = 0;
572  Guarded<ulong> data;
573 
574  if (!GetRootWinProp (GetAtom ("_NET_ACTIVE_WINDOW"), &length, data.GetAs<uchar**> (), XA_WINDOW))
575  return 0;
576 
577  if (!length)
578  return 0;
579 
580  return data [0];
581  }
582 
583  int XWrapper::GetDesktopCount ()
584  {
585  ulong length = 0;
586  Guarded<ulong> data;
587 
588  if (GetRootWinProp (GetAtom ("_NET_NUMBER_OF_DESKTOPS"), &length, data.GetAs<uchar**> (), XA_CARDINAL))
589  return length > 0 ? data [0] : -1;
590 
591  return -1;
592  }
593 
594  int XWrapper::GetCurrentDesktop ()
595  {
596  ulong length = 0;
597  Guarded<ulong> data;
598 
599  if (GetRootWinProp (GetAtom ("_NET_CURRENT_DESKTOP"), &length, data.GetAs<uchar**> (), XA_CARDINAL))
600  return length > 0 ? data [0] : -1;
601 
602  return -1;
603  }
604 
605  void XWrapper::SetCurrentDesktop (int desktop)
606  {
607  SendMessage (AppWin_, GetAtom ("_NET_CURRENT_DESKTOP"), desktop);
608  }
609 
610  QStringList XWrapper::GetDesktopNames ()
611  {
612  ulong length = 0;
613  Guarded<uchar> data;
614 
615  if (!GetRootWinProp (GetAtom ("_NET_DESKTOP_NAMES"),
616  &length, data.GetAs<uchar**> (), GetAtom ("UTF8_STRING")))
617  return {};
618 
619  if (!data)
620  return {};
621 
622  QStringList result;
623  for (char *pos = data.GetAs<char*> (false), *end = data.GetAs<char*> (false) + length; pos < end; )
624  {
625  const auto& str = QString::fromUtf8 (pos);
626  result << str;
627  pos += str.toUtf8 ().size () + 1;
628  }
629  return result;
630  }
631 
632  QString XWrapper::GetDesktopName (int desktop, const QString& def)
633  {
634  return GetDesktopNames ().value (desktop, def);
635  }
636 
637  int XWrapper::GetWindowDesktop (Window wid)
638  {
639  ulong length = 0;
640  Guarded<ulong> data;
641  if (GetWinProp (wid, GetAtom ("_NET_WM_DESKTOP"), &length, data.GetAs<uchar**> (), XA_CARDINAL) && length)
642  return data [0];
643 
644  if (GetWinProp (wid, GetAtom ("_WIN_WORKSPACE"), &length, data.GetAs<uchar**> (), XA_CARDINAL) && length)
645  return data [0];
646 
647  return -1;
648  }
649 
650  void XWrapper::MoveWindowToDesktop (Window wid, int num)
651  {
652  unsigned long data = num;
653  XChangeProperty (QX11Info::display (),
654  wid,
655  GetAtom ("_NET_WM_DESKTOP"),
656  XA_CARDINAL,
657  32,
658  PropModeReplace,
659  reinterpret_cast<unsigned char*> (&data),
660  1);
661  }
662 
663  QRect XWrapper::GetAvailableGeometry (int screen)
664  {
665  auto dw = QApplication::desktop ();
666 
667  if (screen < 0 || screen >= dw->screenCount ())
668  screen = dw->primaryScreen ();
669 
670  if (dw->isVirtualDesktop ())
671  screen = DefaultScreen (Display_);
672 
673  auto available = dw->screenGeometry (screen);
674  const auto deskGeom = dw->rect ();
675 
676  for (const auto wid : GetWindows ())
677  {
678  ulong length = 0;
679  Guarded<ulong> struts;
680  const auto status = GetWinProp (wid, GetAtom ("_NET_WM_STRUT_PARTIAL"),
681  &length, struts.GetAs<uchar**> (), XA_CARDINAL);
682  if (!status || length != 12)
683  continue;
684 
685  const QRect left
686  {
687  static_cast<int> (deskGeom.x ()),
688  static_cast<int> (deskGeom.y () + struts [4]),
689  static_cast<int> (struts [0]),
690  static_cast<int> (struts [5] - struts [4])
691  };
692  if (available.intersects (left))
693  available.setX (left.width ());
694 
695  const QRect right
696  {
697  static_cast<int> (deskGeom.x () + deskGeom.width () - struts [1]),
698  static_cast<int> (deskGeom.y () + struts [6]),
699  static_cast<int> (struts [1]),
700  static_cast<int> (struts [7] - struts [6])
701  };
702  if (available.intersects (right))
703  available.setWidth (right.x () - available.x ());
704 
705  const QRect top
706  {
707  static_cast<int> (deskGeom.x () + struts [8]),
708  static_cast<int> (deskGeom.y ()),
709  static_cast<int> (struts [9] - struts [8]),
710  static_cast<int> (struts [2])
711  };
712  if (available.intersects (top))
713  available.setY (top.height ());
714 
715  const QRect bottom
716  {
717  static_cast<int> (deskGeom.x () + struts [10]),
718  static_cast<int> (deskGeom.y () + deskGeom.height () - struts [3]),
719  static_cast<int> (struts [11] - struts [10]),
720  static_cast<int> (struts [3])
721  };
722  if (available.intersects (bottom))
723  available.setHeight (bottom.y () - available.y ());
724  }
725 
726  return available;
727  }
728 
729  QRect XWrapper::GetAvailableGeometry (QWidget *widget)
730  {
731  return GetAvailableGeometry (QApplication::desktop ()->screenNumber (widget));
732  }
733 
734  Atom XWrapper::GetAtom (const QString& name)
735  {
736  if (Atoms_.contains (name))
737  return Atoms_ [name];
738 
739  auto atom = XInternAtom (Display_, name.toLocal8Bit (), false);
740  Atoms_ [name] = atom;
741  return atom;
742  }
743 
744  bool XWrapper::GetWinProp (Window win, Atom property,
745  ulong *length, unsigned char **result, Atom req) const
746  {
747  int fmt = 0;
748  ulong type = 0, rest = 0;
749  return XGetWindowProperty (Display_, win,
750  property, 0, 1024, false, req, &type,
751  &fmt, length, &rest, result) == Success;
752  }
753 
754  bool XWrapper::GetRootWinProp (Atom property,
755  ulong *length, uchar **result, Atom req) const
756  {
757  return GetWinProp (AppWin_, property, length, result, req);
758  }
759 
760  QList<Atom> XWrapper::GetWindowType (Window wid)
761  {
762  QList<Atom> result;
763 
764  ulong length = 0;
765  ulong *data = nullptr;
766 
767  if (!GetWinProp (wid, GetAtom ("_NET_WM_WINDOW_TYPE"),
768  &length, reinterpret_cast<uchar**> (&data)))
769  return result;
770 
771  for (ulong i = 0; i < length; ++i)
772  result << data [i];
773 
774  XFree (data);
775  return result;
776  }
777 
778  bool XWrapper::SendMessage (Window wid, Atom atom, ulong d0, ulong d1, ulong d2, ulong d3, ulong d4)
779  {
780  XEvent msg;
781  msg.xclient.window = wid;
782  msg.xclient.type = ClientMessage;
783  msg.xclient.message_type = atom;
784  msg.xclient.send_event = true;
785  msg.xclient.display = Display_;
786  msg.xclient.format = 32;
787  msg.xclient.data.l [0] = d0;
788  msg.xclient.data.l [1] = d1;
789  msg.xclient.data.l [2] = d2;
790  msg.xclient.data.l [3] = d3;
791  msg.xclient.data.l [4] = d4;
792 
793  auto flags = SubstructureRedirectMask | SubstructureNotifyMask;
794  return XSendEvent (Display_, AppWin_, false, flags, &msg) == Success;
795  }
796 
797  void XWrapper::initialize ()
798  {
799  }
800 }
801 }
constexpr detail::AggregateType< detail::AggregateFunction::Count > count
Definition: oral.h:936
detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, boost::mpl::int_< Idx > > pos
Definition: oral.h:922
union _XEvent XEvent
Definition: xwrapper.h:49
const int StateRemove
Definition: xwrapper.cpp:53
const int StateAdd
Definition: xwrapper.cpp:54
const int SourcePager
Definition: xwrapper.cpp:51
No type (item doesn&#39;t correspond to a radio station).
unsigned long Window
Definition: xwrapper.h:44