procedure TFPWMClient.activateAndWarp();
begin
    {$ifdef FPWM_TRACE}
    FPWMTrace('[TFPWMClient.activateAndWarp]');
    {$endif}
    mapRaised();
    ensureVisible();
    XWarpPointer(display(), None, parent(), 0, 0, 0, 0,
	 m_border.xIndent() div 2, m_border.xIndent() + 8);
    activate();
end;
procedure TFPWMClient.eventButton(e: PXButtonEvent);
begin
  {$ifdef FPWM_TRACE}
  FPWMTrace(Format('[TFPWMClient.eventButton] e.type=%d ButtonPress=4', [e^._type]));
  {$endif}
  if (e^._type <> ButtonPress) then Exit();
  mapRaised();
  if (e^.button = Button1) then
  begin
    if (m_border.hasWindow(e^.window)) then
    begin
      m_border.eventButton(e);
    end;
  end;
  if (not isNormal()) or isActive() or (e^.send_event <> 0) then Exit();
  activate();
end;
procedure TFPWMClient.move(e: PXButtonEvent);
var
   x: Integer;
   y: Integer;
   xoff: Integer;
   yoff: Integer;
   done: Boolean;
   event: TXEvent;
   found: Boolean;
   doSomething: Boolean;
begin
  {$ifdef FPWM_TRACE}
  FPWMTrace('[TFPWMClient.move]');
  {$endif}
  x := -1;
  y := -1;
  done := False;
  if (m_windowManager.attemptGrab(root(), None, DragMask, e^.time) <> GrabSuccess) then
  begin
    {$ifdef FPWM_TRACE}
    FPWMTrace('[TFPWMClient.move] attemptGrab <> GrabSuccess');
    {$endif}
    Exit();
  end;
  xoff := m_border.xIndent() - e^.x;
  yoff := m_border.yIndent() - e^.y;
  doSomething := False;
  while (not done) do
  begin
      found := False;
      while (XCheckMaskEvent(display(), DragMask or ExposureMask, @event)) do
      begin
	  found := True;
	  if (event._type <> MotionNotify) then break;
      end;
      if (not found) then
      begin
	  Sleep(50);
	  continue;
      end;
      case (event._type) of
      Expose: m_windowManager.eventExposure(@event.xexpose);
      ButtonPress:
      begin
	  XUngrabPointer(display(), event.xbutton.time);
	  doSomething := False;
	  done := True;
      end;
      ButtonRelease:
      begin
	  x := event.xbutton.x; y := event.xbutton.y;
	  if (not nobuttons(@event.xbutton)) then doSomething := False;
	  m_windowManager.releaseGrab(@event.xbutton);
	  done := True;
      end;
      MotionNotify:
      begin
	  x := event.xbutton.x; y := event.xbutton.y;
	  if (x + xoff <> m_x) or (y + yoff <> m_y) then
          begin
	      windowManager().showGeometry(x + xoff, y + yoff);
	      m_border.moveTo(x + xoff, y + yoff);
	      doSomething := True;
	  end;
      end;
      else
        WriteLn(Format('fpwm: unknown event type %d', [event._type]));
      end;
  end;
  windowManager().removeGeometry();
  if (x >= 0) and doSomething then
  begin
      m_x := x + xoff;
      m_y := y + yoff;
  end;
  {$ifdef FPWM_TRACE}
  FPWMTrace(Format('[TFPWMClient.move] x=%d y=%d m_x=%d m_y=%d doSomething=%d',
    [x, y, m_x, m_y, Integer(doSomething)]));
  {$endif}
  if (CONFIG_CLICK_TO_FOCUS) then activate();
  m_border.moveTo(m_x, m_y);
  sendConfigureNotify();
end;
procedure TFPWMClient.fixResizeDimensions(var w, h, dw, dh: cint);
begin
    {$ifdef FPWM_TRACE}
    FPWMTrace('[TFPWMClient.fixResizeDimensions]');
    {$endif}
    if (w < 50) then w := 50;
    if (h < 50) then h := 50;
    if (m_sizeHints.flags and PResizeInc) <> 0 then
    begin
	w := m_minWidth + (((w - m_minWidth) div m_sizeHints.width_inc) *
			   m_sizeHints.width_inc);
	h := m_minHeight + (((h - m_minHeight) div m_sizeHints.height_inc) *
			   m_sizeHints.height_inc);
	dw := (w - m_minWidth) div m_sizeHints.width_inc;
	dh := (h - m_minHeight) div m_sizeHints.height_inc;
    end
    else
    begin
	dw := w; dh := h;
    end;
    if (m_sizeHints.flags and PMaxSize) <> 0 then
    begin
	if (w > m_sizeHints.max_width) then  w := m_sizeHints.max_width;
	if (h > m_sizeHints.max_height) then h := m_sizeHints.max_height;
    end;
    if (w < m_minWidth) then w := m_minWidth;
    if (h < m_minHeight) then h := m_minHeight;
end;
procedure TFPWMClient.resize(e: PXButtonEvent; horizontal, vertical: Boolean);
label LoopStart;
var
   dummy: TWindow;
   xorig: Integer;
   yorig: Integer;
   x: Integer;
   y: Integer;
   w: Integer;
   h: Integer;
   prevW: Integer;
   prevH: Integer;
   dw: Integer;
   dh: Integer;
   event: TXEvent;
   found: Boolean;
   doSomething: Boolean;
   done: Boolean;
begin
    {$ifdef FPWM_TRACE}
    FPWMTrace('[TFPWMClient.resize]');
    {$endif}
    if (isFixedSize()) then Exit();
    if (m_windowManager.attemptGrab(root(), None, DragMask, e^.time) <> GrabSuccess) then Exit();
    if (vertical and horizontal) then
	m_windowManager.installCursor(DownrightCursor)
    else if (vertical) then
	m_windowManager.installCursor(DownCursor)
    else
	m_windowManager.installCursor(RightCursor);
    XTranslateCoordinates(display(), e^.window, parent(),
			  e^.x, e^.y, @e^.x, @e^.y, @dummy);
    xorig := e^.x;
    yorig := e^.y;
    x := xorig;
    y := yorig;
    w := m_w;
    h := m_h;
    doSomething := False;
    done := False;
    while (not done) do
    begin
LoopStart:
        found := False;
	while (XCheckMaskEvent(display(), DragMask or ExposureMask, @event)) do
        begin
	    found := True;
	    if (event._type <> MotionNotify) then Break;
	end;
	if (not found) then
        begin
	    Sleep(50);
	    continue;
	end;
	case (event._type) of
	Expose:	m_windowManager.eventExposure(@event.xexpose);
	ButtonPress:
        begin
	    XUngrabPointer(display(), event.xbutton.time);
	    done := True;
	end;
	ButtonRelease:
        begin
	    x := event.xbutton.x; y := event.xbutton.y;
	    if (not nobuttons(@event.xbutton)) then x := -1;
	    m_windowManager.releaseGrab(@event.xbutton);
	    done := True;
        end;
	MotionNotify:
        begin
	    x := event.xbutton.x; y := event.xbutton.y;
	    if (vertical and horizontal) then
            begin
		prevH := h; h := y - m_y;
		prevW := w; w := x - m_x;
		fixResizeDimensions(w, h, dw, dh);
		if (h = prevH) and (w = prevW) then goto LoopStart;
		m_border.configure(m_x, m_y, w, h, CWWidth or CWHeight, 0);
		windowManager().showGeometry(dw, dh);
		doSomething := True;
	    end
            else if (vertical) then
            begin
		prevH := h; h := y - m_y;
		fixResizeDimensions(w, h, dw, dh);
		if (h = prevH) then goto LoopStart;
		m_border.configure(m_x, m_y, w, h, CWHeight, 0);
		windowManager().showGeometry(dw, dh);
		doSomething := True;
	    end
            else
            begin
		prevW := w; w := x - m_x;
		fixResizeDimensions(w, h, dw, dh);
		if (w = prevW) then goto LoopStart;
		m_border.configure(m_x, m_y, w, h, CWWidth, 0);
		windowManager().showGeometry(dw, dh);
		doSomething := True;
	    end;
	end;
        else
          WriteLn(Format('wm2: unknown event type %d', [event._type]));
	end;
    end;
    if (doSomething) then
    begin
	windowManager().removeGeometry();
	if (vertical and horizontal) then
        begin
	    m_w := x - m_x;
	    m_h := y - m_y;
	    fixResizeDimensions(m_w, m_h, dw, dh);
	    m_border.configure(m_x, m_y, m_w, m_h, CWWidth or CWHeight, 0, True);
	end
        else if (vertical) then
        begin
	    m_h := y - m_y;
	    fixResizeDimensions(m_w, m_h, dw, dh);
	    m_border.configure(m_x, m_y, m_w, m_h, CWHeight, 0, True);
	end
        else
        begin
	    m_w := x - m_x;
	    fixResizeDimensions(m_w, m_h, dw, dh);
	    m_border.configure(m_x, m_y, m_w, m_h, CWWidth, 0, True);
	end;
	XMoveResizeWindow(display(), m_window,
			  m_border.xIndent(), m_border.yIndent(), m_w, m_h);
	sendConfigureNotify();
    end;
    m_windowManager.installCursor(NormalCursor);
end;
procedure TFPWMClient.moveOrResize(e: PXButtonEvent);
begin
    {$ifdef FPWM_TRACE}
    FPWMTrace('[TFPWMClient.moveOrResize]');
    {$endif}
    if (e^.x < m_border.xIndent) and (e^.y > m_h) then
    begin
	resize(e, False, True);
    end
    else if (e^.y < m_border.yIndent) and
       (e^.x > m_w + m_border.xIndent - m_border.yIndent) then 
    begin
	resize(e, True, False);
    end
    else
    begin
	move(e);
    end;
end;