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