text: /*
   * Copyright (C) 2017 ~ 2017 Deepin Technology Co., Ltd.
   *
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, either version 3 of the License, or
   * any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  #include "xutil.h"
  
  #include <QDebug>
  #include <QTimer>
  #include <QWidget>
  
  #include <QX11Info>
  
  #include <X11/Xatom.h>
  #include <X11/Xlib.h>
  #include <X11/extensions/shape.h>
  
  QT_BEGIN_NAMESPACE
  
  namespace XUtils
  {
  // From the WM spec
  #define _NET_WM_MOVERESIZE_INVALID          -1
  #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT      0
  #define _NET_WM_MOVERESIZE_SIZE_TOP          1
  #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT     2
  #define _NET_WM_MOVERESIZE_SIZE_RIGHT        3
  #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT  4
  #define _NET_WM_MOVERESIZE_SIZE_BOTTOM       5
  #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT   6
  #define _NET_WM_MOVERESIZE_SIZE_LEFT         7
  #define _NET_WM_MOVERESIZE_MOVE              8   /* movement only */
  #define _NET_WM_MOVERESIZE_SIZE_KEYBOARD     9   /* size via keyboard */
  #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD    10   /* move via keyboard */
  #define _NET_WM_MOVERESIZE_CANCEL           11   /* cancel operation */
  
  #define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
  #define _NET_WM_STATE_ADD           1    /* add/set property */
  #define _NET_WM_STATE_TOGGLE        2    /* toggle property  */
  
  const char kAtomNameHidden[] = "_NET_WM_STATE_HIDDEN";
  const char kAtomNameFullscreen[] = "_NET_WM_STATE_FULLSCREEN";
  const char kAtomNameMaximizedHorz[] = "_NET_WM_STATE_MAXIMIZED_HORZ";
  const char kAtomNameMaximizedVert[] = "_NET_WM_STATE_MAXIMIZED_VERT";
  const char kAtomNameMoveResize[] = "_NET_WM_MOVERESIZE";
  const char kAtomNameWmState[] = "_NET_WM_STATE";
  const char kAtomNameWmStateAbove[] = "_NET_WM_STATE_ABOVE";
  const char kAtomNameWmStateStaysOnTop[] = "_NET_WM_STATE_STAYS_ON_TOP";
  const char kAtomNameWmSkipTaskbar[] = "_NET_WM_STATE_SKIP_TASKBAR";
  const char kAtomNameWmSkipPager[] = "_NET_WM_STATE_SKIP_PAGER";
  
  struct MwmHints {
  	unsigned long flags;
  	unsigned long functions;
  	unsigned long decorations;
  	long input_mode;
  	unsigned long status;
  };
  
  enum {
  	MWM_HINTS_FUNCTIONS = (1L << 0),
  	MWM_HINTS_DECORATIONS = (1L << 1),
  
  	MWM_FUNC_ALL = (1L << 0),
  	MWM_FUNC_RESIZE = (1L << 1),
  	MWM_FUNC_MOVE = (1L << 2),
  	MWM_FUNC_MINIMIZE = (1L << 3),
  	MWM_FUNC_MAXIMIZE = (1L << 4),
  	MWM_FUNC_CLOSE = (1L << 5),
  
  	MWM_DECOR_ALL      = (1L << 0),
  	MWM_DECOR_BORDER   = (1L << 1),
  	MWM_DECOR_RESIZEH  = (1L << 2),
  	MWM_DECOR_TITLE    = (1L << 3),
  	MWM_DECOR_MENU     = (1L << 4),
  	MWM_DECOR_MINIMIZE = (1L << 5),
  	MWM_DECOR_MAXIMIZE = (1L << 6),
  
  	MWM_HINTS_INPUT_MODE = (1L << 2),
  
  	MWM_INPUT_MODELESS                  = 0L,
  	MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L,
  	MWM_INPUT_FULL_APPLICATION_MODAL    = 3L
  };
  
  static int CornerEdge2WmGravity(const CornerEdge &ce)
  {
  	switch (ce) {
  	case CornerEdge::kTopLeft:     return _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
  	case CornerEdge::kTop:         return _NET_WM_MOVERESIZE_SIZE_TOP;
  	case CornerEdge::kTopRight:    return _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
  	case CornerEdge::kRight:       return _NET_WM_MOVERESIZE_SIZE_RIGHT;
  	case CornerEdge::kBottomRight: return _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
  	case CornerEdge::kBottom:      return _NET_WM_MOVERESIZE_SIZE_BOTTOM;
  	case CornerEdge::kBottomLeft:  return _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
  	case CornerEdge::kLeft:        return _NET_WM_MOVERESIZE_SIZE_LEFT;
  	default:                       return _NET_WM_MOVERESIZE_INVALID;
  	}
  }
  
  static XCursorType CornerEdge2XCursor(const CornerEdge &ce)
  {
  	switch (ce) {
  	case CornerEdge::kTop:         return XCursorType::kTop;
  	case CornerEdge::kTopRight:    return XCursorType::kTopRight;
  	case CornerEdge::kRight:       return XCursorType::kRight;
  	case CornerEdge::kBottomRight: return XCursorType::kBottomRight;
  	case CornerEdge::kBottom:      return XCursorType::kBottom;
  	case CornerEdge::kBottomLeft:  return XCursorType::kBottomLeft;
  	case CornerEdge::kLeft:        return XCursorType::kLeft;
  	case CornerEdge::kTopLeft:     return XCursorType::kTopLeft;
  	default:                       return XCursorType::kInvalid;
  	}
  }
  
  void ChangeWindowMaximizedState(const QWidget *widget, int wm_state)
  {
  	const auto display = QX11Info::display();
  	const auto screen = QX11Info::appScreen();
  
  	XEvent xev;
  	memset(&xev, 0, sizeof(xev));
  	const Atom net_wm_state = XInternAtom(display, kAtomNameWmState, false);
  	const Atom vertical_maximized = XInternAtom(display,
  									kAtomNameMaximizedVert,
  									false);
  	const Atom horizontal_maximized = XInternAtom(display,
  									  kAtomNameMaximizedHorz,
  									  false);
  
  	xev.xclient.type = ClientMessage;
  	xev.xclient.message_type = net_wm_state;
  	xev.xclient.display = display;
  	xev.xclient.window = widget->winId();
  	xev.xclient.format = 32;
  
  	xev.xclient.data.l[0] = wm_state;
  	xev.xclient.data.l[1] = vertical_maximized;
  	xev.xclient.data.l[2] = horizontal_maximized;
  	xev.xclient.data.l[3] = 1;
  
  	XSendEvent(display,
  			   QX11Info::appRootWindow(screen),
  			   false,
  			   SubstructureRedirectMask | SubstructureNotifyMask,
  			   &xev);
  	XFlush(display);
  }
  
  CornerEdge GetCornerEdge(const QWidget *widget, int x, int y, const QMargins &margins, int border_width)
  {
  	QRect fullRect = widget->rect();
  	fullRect = fullRect.marginsRemoved(margins);
  	unsigned int ce = static_cast<unsigned int>(CornerEdge::kInvalid);
  	if ((y - fullRect.top() >= -border_width)
  			&& (y < fullRect.top())) {
  		ce = ce | static_cast<unsigned int>(CornerEdge::kTop);
  	}
  	if ((x - fullRect.left() >= -border_width)
  			&& (x < fullRect.left())) {
  		ce = ce | static_cast<unsigned int>(CornerEdge::kLeft);
  	}
  	if ((y - fullRect.bottom() <= border_width)
  			&& (y > fullRect.bottom())) {
  		ce = ce | static_cast<unsigned int>(CornerEdge::kBottom);
  	}
  	if ((x - fullRect.right() <= border_width)
  			&& (x > fullRect.right())) {
  		ce = ce | static_cast<unsigned int>(CornerEdge::kRight);
  	}
  	return static_cast<CornerEdge>(ce);
  }
  
  void SendMoveResizeMessage(const QWidget *widget, Qt::MouseButton qbutton, int action)
  {
  	const auto display = QX11Info::display();
  	const auto screen = QX11Info::appScreen();
  
  	int xbtn = qbutton == Qt::LeftButton ? Button1 :
  			   qbutton == Qt::RightButton ? Button3 :
  			   AnyButton;
  
  	XEvent xev;
  	memset(&xev, 0, sizeof(xev));
  	const Atom net_move_resize = XInternAtom(display, kAtomNameMoveResize, false);
  	xev.xclient.type = ClientMessage;
  	xev.xclient.message_type = net_move_resize;
  	xev.xclient.display = display;
  	xev.xclient.window = widget->winId();
  	xev.xclient.format = 32;
  
  	const auto global_position = QCursor::pos();
  	xev.xclient.data.l[0] = global_position.x();
  	xev.xclient.data.l[1] = global_position.y();
  	xev.xclient.data.l[2] = action;
  	xev.xclient.data.l[3] = xbtn;
  	xev.xclient.data.l[4] = 0;
  	XUngrabPointer(display, QX11Info::appTime());
  
  	XSendEvent(display,
  			   QX11Info::appRootWindow(screen),
  			   false,
  			   SubstructureRedirectMask | SubstructureNotifyMask,
  			   &xev);
  	XFlush(display);
  }
  
  bool IsCornerEdget(const QWidget *widget, int x, int y, const QMargins &margins, int border_width)
  {
  	return GetCornerEdge(widget, x, y, margins, border_width) != CornerEdge::kInvalid;
  }
  
  void MoveWindow(const QWidget *widget, Qt::MouseButton qbutton)
  {
  	SendMoveResizeMessage(widget, qbutton, _NET_WM_MOVERESIZE_MOVE);
  }
  
  void MoveResizeWindow(const QWidget *widget, Qt::MouseButton qbutton, int x, int y, const QMargins &margins, int border_width)
  {
  	const CornerEdge ce = GetCornerEdge(widget, x, y, margins, border_width);
  	if (ce != CornerEdge::kInvalid) {
  		const int action = CornerEdge2WmGravity(ce);
  		SendMoveResizeMessage(widget, qbutton, action);
  	}
  }
  
  void ResetCursorShape(const QWidget *widget)
  {
  	const auto display = QX11Info::display();
  	const WId window_id = widget->winId();
  	XUndefineCursor(display, window_id);
  	XFlush(display);
  }
  
  bool SetCursorShape(const QWidget *widget, int cursor_id)
  {
  	const auto display = QX11Info::display();
  	const WId window_id = widget->winId();
  	const Cursor cursor = XCreateFontCursor(display, cursor_id);
  	if (!cursor) {
  		qWarning() << "[ui]::SetCursorShape() call XCreateFontCursor() failed";
  		return false;
  	}
  	const int result = XDefineCursor(display, window_id, cursor);
  	XFlush(display);
  	return result == Success;
  }
  
  void SendButtonRelease(const QWidget *widget,
  									 const QPoint &pos, const QPoint &globalPos)
  {
  	const auto display = QX11Info::display();
  	const auto screen = QX11Info::appScreen();
  
  	XEvent xevent;
  	memset(&xevent, 0, sizeof(XEvent));
  
  	xevent.type = ButtonRelease;
  	xevent.xbutton.button = Button1;
  	xevent.xbutton.window = widget->effectiveWinId();
  	xevent.xbutton.x = pos.x();
  	xevent.xbutton.y = pos.y();
  	xevent.xbutton.x_root = globalPos.x();
  	xevent.xbutton.y_root = globalPos.y();
  	xevent.xbutton.display = display;
  
  	XSendEvent(display, widget->effectiveWinId(), False, ButtonReleaseMask, &xevent);
  	XFlush(display);
  }
  
  void ShowFullscreenWindow(const QWidget *widget, bool is_fullscreen)
  {
  	const auto display = QX11Info::display();
  	const auto screen = QX11Info::appScreen();
  
  	XEvent xev;
  	memset(&xev, 0, sizeof(xev));
  	const Atom net_wm_state = XInternAtom(display, kAtomNameWmState, false);
  	const Atom fullscreen = XInternAtom(display, kAtomNameFullscreen, false);
  	xev.xclient.type = ClientMessage;
  	xev.xclient.message_type = net_wm_state;
  	xev.xclient.display = display;
  	xev.xclient.window = widget->winId();
  	xev.xclient.format = 32;
  
  	if (is_fullscreen) {
  		xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
  	} else {
  		xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
  	}
  	xev.xclient.data.l[1] = fullscreen;
  	xev.xclient.data.l[2] = 0;
  	xev.xclient.data.l[3] = 1;
  
  	XSendEvent(display,
  			   QX11Info::appRootWindow(screen),
  			   false,
  			   SubstructureRedirectMask | SubstructureNotifyMask,
  			   &xev
  			  );
  	XFlush(display);
  }
  
  void ShowMaximizedWindow(const QWidget *widget)
  {
  	ChangeWindowMaximizedState(widget, _NET_WM_STATE_ADD);
  }
  
  void ShowMinimizedWindow(const QWidget *widget, bool minimized)
  {
  	const auto display = QX11Info::display();
  	const auto screen = QX11Info::appScreen();
  
  	XEvent xev;
  	memset(&xev, 0, sizeof(xev));
  	const Atom net_wm_state = XInternAtom(display, kAtomNameWmState, false);
  	const Atom hidden = XInternAtom(display, kAtomNameHidden, false);
  	xev.xclient.type = ClientMessage;
  	xev.xclient.message_type = net_wm_state;
  	xev.xclient.display = display;
  	xev.xclient.window = widget->winId();
  	xev.xclient.format = 32;
  
  	if (minimized) {
  		xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
  	} else {
  		xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
  	}
  	xev.xclient.data.l[1] = hidden;
  	xev.xclient.data.l[2] = 0;
  	xev.xclient.data.l[3] = 1;
  
  	XSendEvent(display,
  			   QX11Info::appRootWindow(screen),
  			   false,
  			   SubstructureRedirectMask | SubstructureNotifyMask,
  			   &xev
  			  );
  
  	XIconifyWindow(display, widget->winId(), screen);
  	XFlush(display);
  }
  
  void ShowNormalWindow(const QWidget *widget)
  {
  	ChangeWindowMaximizedState(widget, _NET_WM_STATE_REMOVE);
  }
  
  void ToggleMaximizedWindow(const QWidget *widget)
  {
  	ChangeWindowMaximizedState(widget, _NET_WM_STATE_TOGGLE);
  }
  
  bool UpdateCursorShape(const QWidget *widget, int x, int y, const QMargins &margins, int border_width)
  {
  	const CornerEdge ce = GetCornerEdge(widget, x, y, margins, border_width);
  	const XCursorType x_cursor = CornerEdge2XCursor(ce);
  	if (x_cursor != XCursorType::kInvalid)
  	{
  		return SetCursorShape(widget, static_cast<unsigned int>(x_cursor));
  	}
  	else
  	{
  		ResetCursorShape(widget);
  		return false;
  	}
  }
  
  void SkipTaskbarPager(const QWidget *widget)
  {
  	Q_ASSERT(widget);
  
  	const auto display = QX11Info::display();
  	const auto screen = QX11Info::appScreen();
  
  	const auto wmStateAtom = XInternAtom(display, kAtomNameWmState, false);
  	const auto taskBarAtom = XInternAtom(display, kAtomNameWmSkipTaskbar, false);
  	const auto noPagerAtom = XInternAtom(display, kAtomNameWmSkipPager, false);
  
  	XEvent xev;
  	memset(&xev, 0, sizeof(xev));
  
  	xev.xclient.type = ClientMessage;
  	xev.xclient.message_type = wmStateAtom;
  	xev.xclient.display = display;
  	xev.xclient.window = widget->winId();;
  	xev.xclient.format = 32;
  
  	xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
  	xev.xclient.data.l[1] = taskBarAtom;
  	xev.xclient.data.l[2] = noPagerAtom;
  	xev.xclient.data.l[3] = 1;
  
  	XSendEvent(display,
  			   QX11Info::appRootWindow(screen),
  			   false,
  			   SubstructureRedirectMask | SubstructureNotifyMask,
  			   &xev);
  	XFlush(display);
  }
  
  void SetStayOnTop(const QWidget *widget, bool on)
  {
  	Q_ASSERT(widget);
  
  	const auto display = QX11Info::display();
  	const auto screen = QX11Info::appScreen();
  
  	const auto wmStateAtom = XInternAtom(display, kAtomNameWmState, false);
  	const auto stateAboveAtom = XInternAtom(display, kAtomNameWmStateAbove, false);
  	const auto stateStaysOnTopAtom = XInternAtom(display,
  									 kAtomNameWmStateStaysOnTop,
  									 false);
  
  	XEvent xev;
  	memset(&xev, 0, sizeof(xev));
  
  	xev.xclient.type = ClientMessage;
  	xev.xclient.message_type = wmStateAtom;
  	xev.xclient.display = display;
  	xev.xclient.window = widget->winId();
  	xev.xclient.format = 32;
  
  	xev.xclient.data.l[0] = on ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
  	xev.xclient.data.l[1] = stateAboveAtom;
  	xev.xclient.data.l[2] = stateStaysOnTopAtom;
  	xev.xclient.data.l[3] = 1;
  
  	XSendEvent(display,
  			   QX11Info::appRootWindow(screen),
  			   false,
  			   SubstructureRedirectMask | SubstructureNotifyMask,
  			   &xev);
  	XFlush(display);
  }
  
  void SetMouseTransparent(const QWidget *widget, bool on)
  {
  	Q_ASSERT(widget);
  
  	const auto display = QX11Info::display();
  	XRectangle XRect;
  	XRect.x = 0;
  	XRect.y = 0;
  	int nRects = 0;
  
  	if (on) {
  		XRect.width = 0;
  		XRect.height = 0;
  		nRects = 0;
  	} else {
  		XRect.width = widget->width();
  		XRect.height = widget->height();
  		nRects = 1;
  	}
  	XShapeCombineRectangles(display, widget->winId(), ShapeInput,
  							0, 0,
  							&XRect, nRects, ShapeSet, YXBanded);
  }
  
  void SetWindowExtents(const QWidget *widget, const QMargins &margins, const int resizeHandleWidth)
  {
  	SetWindowExtents(widget->winId(), widget->rect(), margins, resizeHandleWidth);
  }
  
  
  void PropagateSizeHints(const QWidget *w)
  {
  	const auto display = QX11Info::display();
  	XSizeHints *sh = XAllocSizeHints();
  	sh->flags = PPosition | PSize | PMinSize | PMaxSize | PResizeInc;
  	sh->x = w->x();
  	sh->y = w->y();
  	sh->min_width = w->minimumWidth();
  	sh->min_height = w->minimumHeight();
  	sh->base_width = w->baseSize().width();
  	sh->base_height = w->baseSize().height();
  	sh->max_width = w->maximumWidth();
  	sh->max_height = w->maximumHeight();
  	sh->width_inc =  w->sizeIncrement().width();
  	sh->height_inc = w->sizeIncrement().height();
  	XSetWMNormalHints(display, w->winId(), sh);
  	XFree(sh);
  }
  
  void DisableResize(const QWidget *w)
  {
  	Display *display = QX11Info::display();
  	Atom mwmHintsProperty = XInternAtom(display, "_MOTIF_WM_HINTS", 0);
  	struct MwmHints *hints;
  	unsigned char *wm_data;
  	Atom wm_type;
  	int wm_format;
  	unsigned long wm_nitems, wm_bytes_after;
  
  	XGetWindowProperty(display,
  					   w->winId(),
  					   mwmHintsProperty,
  					   0,
  					   sizeof(MwmHints) / sizeof(long),
  					   false,
  					   AnyPropertyType,
  					   &wm_type,
  					   &wm_format,
  					   &wm_nitems,
  					   &wm_bytes_after,
  					   &wm_data);
  
  	hints = (MwmHints *) wm_data;
  
  	hints->flags |= MWM_HINTS_FUNCTIONS;
  	if (hints->functions == MWM_FUNC_ALL) {
  		hints->functions = MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE | MWM_FUNC_CLOSE;
  	} else {
  		hints->functions &= ~MWM_FUNC_RESIZE;
  		hints->functions |= MWM_FUNC_CLOSE;
  	}
  
  	if (hints->decorations == MWM_DECOR_ALL) {
  		hints->flags |= MWM_HINTS_DECORATIONS;
  		hints->decorations = (MWM_DECOR_BORDER
  							  | MWM_DECOR_TITLE
  							  | MWM_DECOR_MENU);
  	} else {
  		hints->decorations &= ~MWM_DECOR_RESIZEH;
  	}
  	XChangeProperty(display,
  					w->winId(),
  					mwmHintsProperty,
  					mwmHintsProperty,
  					32,
  					PropModeReplace,
  					(unsigned char *)hints,
  					5);
  }
  
  void StartResizing(const QWidget *w, const QPoint &globalPoint, const CornerEdge &ce)
  {
  	const auto display = QX11Info::display();
  	const auto winId = w->winId();
  	const auto screen = QX11Info::appScreen();
  
  	XEvent xev;
  	const Atom netMoveResize = XInternAtom(display, "_NET_WM_MOVERESIZE", false);
  	xev.xclient.type = ClientMessage;
  	xev.xclient.message_type = netMoveResize;
  	xev.xclient.display = display;
  	xev.xclient.window = winId;
  	xev.xclient.format = 32;
  
  	xev.xclient.data.l[0] = globalPoint.x();
  	xev.xclient.data.l[1] = globalPoint.y();
  	xev.xclient.data.l[2] = CornerEdge2WmGravity(ce);
  	xev.xclient.data.l[3] = Button1;
  	xev.xclient.data.l[4] = 1;
  	XUngrabPointer(display, QX11Info::appTime());
  
  	XSendEvent(display,
  			   QX11Info::appRootWindow(screen),
  			   false,
  			   SubstructureRedirectMask | SubstructureNotifyMask,
  			   &xev);
  	XFlush(display);
  }
  
  void CancelMoveWindow(const QWidget *widget, Qt::MouseButton qbutton)
  {
  	SendMoveResizeMessage(widget, qbutton, _NET_WM_MOVERESIZE_CANCEL);
  }
  
  void SetWindowExtents(uint wid, const QRect &windowRect, const QMargins &margins, const int resizeHandleSize)
  {
  	Atom frameExtents;
  	unsigned long value[4] = {
  		(unsigned long)(margins.left()),
  		(unsigned long)(margins.right()),
  		(unsigned long)(margins.top()),
  		(unsigned long)(margins.bottom())
  	};
  	frameExtents = XInternAtom(QX11Info::display(), "_GTK_FRAME_EXTENTS", False);
  	if (frameExtents == None) {
  		qWarning() << "Failed to create atom with name DEEPIN_WINDOW_SHADOW";
  		return;
  	}
  	XChangeProperty(QX11Info::display(),
  					wid,
  					frameExtents,
  					XA_CARDINAL,
  					32,
  					PropModeReplace,
  					(unsigned char *)value,
  					4);
  
  	QRect tmp_rect = windowRect;
  
  	tmp_rect -= margins;
  
  	XRectangle contentXRect;
  	contentXRect.x = 0;
  	contentXRect.y = 0;
  	contentXRect.width = tmp_rect.width() + resizeHandleSize * 2;
  	contentXRect.height = tmp_rect.height() + resizeHandleSize * 2;
  	XShapeCombineRectangles(QX11Info::display(),
  							wid,
  							ShapeInput,
  							margins.left() - resizeHandleSize,
  							margins.top() - resizeHandleSize,
  							&contentXRect, 1, ShapeSet, YXBanded);
  }
  
  }
  
  QT_END_NAMESPACE
  