program gwm;
{$mode objfpc}{$H+}
uses
  x, xlib, xutil, keysym, ctypes, Math;

const
  BORDER_WIDTH = 2;
  TITLE_HEIGHT = 20;
  BUTTON_WIDTH = 20;
  BUTTON_SPACING = 5;
  COLOR_ACTIVE = $0000FF;
  COLOR_INACTIVE = $888888;
  COLOR_BUTTON = $FF0000;
  COLOR_TEXT = $FFFFFF;
  RESIZE_HANDLE_SIZE = 5;

var
  display: PDisplay;
  root: TWindow;
  event: TXEvent;
  focusedWin: TWindow = 0;
  windows: array of TWindow;
  isMoving: Boolean = False;
  isResizing: Boolean = False;
  moveStartX, moveStartY: Integer;
  resizeStartX, resizeStartY: Integer;
  initialWidth, initialHeight: Integer;

procedure DrawTitleBar(win: TWindow; active: Boolean);
var
  gc: TGC;
  attr: TXWindowAttributes;
  color: LongWord;
  closeBtnX, minimizeBtnX, maximizeBtnX: Integer;
begin
  XGetWindowAttributes(display, win, @attr);
  gc := XCreateGC(display, root, 0, nil);

  // Отрисовка фона заголовка
  color := IfThen(active, COLOR_ACTIVE, COLOR_INACTIVE);
  XSetForeground(display, gc, color);
  XFillRectangle(display, win, gc, 0, 0, attr.width, TITLE_HEIGHT);

  // Отрисовка текста заголовка
  XSetForeground(display, gc, COLOR_TEXT);
  XDrawString(display, win, gc, 5, 15, 'Window', 6);

  // Отрисовка кнопок
  closeBtnX := attr.width - BUTTON_WIDTH;
  minimizeBtnX := closeBtnX - BUTTON_WIDTH - BUTTON_SPACING;
  maximizeBtnX := minimizeBtnX - BUTTON_WIDTH - BUTTON_SPACING;

  // Кнопка закрытия (красная)
  XSetForeground(display, gc, $FF0000);
  XFillRectangle(display, win, gc, closeBtnX, 0, BUTTON_WIDTH, TITLE_HEIGHT);

  // Кнопка сворачивания (жёлтая)
  XSetForeground(display, gc, $FFFF00);
  XFillRectangle(display, win, gc, minimizeBtnX, 0, BUTTON_WIDTH, TITLE_HEIGHT);

  // Кнопка разворачивания (зелёная)
  XSetForeground(display, gc, $00FF00);
  XFillRectangle(display, win, gc, maximizeBtnX, 0, BUTTON_WIDTH, TITLE_HEIGHT);

  XFreeGC(display, gc);
end;

procedure ManageWindow(win: TWindow);
begin
  XSelectInput(display, win, StructureNotifyMask or FocusChangeMask or ButtonPressMask or ButtonReleaseMask or PointerMotionMask);
  DrawTitleBar(win, False);
  SetLength(windows, Length(windows) + 1);
  windows[High(windows)] := win;
end;

procedure FocusNextWindow;
var
  idx, i: Integer;
begin
  if Length(windows) = 0 then Exit;
  idx := -1;
  for i := 0 to High(windows) do
    if windows[i] = focusedWin then
    begin
      idx := i;
      Break;
    end;
  
  if idx = -1 then focusedWin := windows[0]
  else focusedWin := windows[(idx + 1) mod Length(windows)];
  DrawTitleBar(focusedWin, True);
end;

procedure HandleEvent;
var
  x, y: Integer;
  closeBtnX, minimizeBtnX, maximizeBtnX: Integer;
  attr: TXWindowAttributes;
  newX, newY, newWidth, newHeight: Integer;
begin
  case event._type of
    MapRequest:
      begin
        ManageWindow(event.xmaprequest.window);
        XMapWindow(display, event.xmaprequest.window);
      end;
    ButtonPress:
      begin
        focusedWin := event.xbutton.window;
        XGetWindowAttributes(display, focusedWin, @attr);

        x := event.xbutton.x;
        y := event.xbutton.y;

        closeBtnX := attr.width - BUTTON_WIDTH;
        minimizeBtnX := closeBtnX - BUTTON_WIDTH - BUTTON_SPACING;
        maximizeBtnX := minimizeBtnX - BUTTON_WIDTH - BUTTON_SPACING;

        if (y >= 0) and (y <= TITLE_HEIGHT) then
        begin
          if (x >= closeBtnX) and (x <= closeBtnX + BUTTON_WIDTH) then
          begin
            // Закрыть окно
            XDestroyWindow(display, focusedWin);
          end
          else if (x >= minimizeBtnX) and (x <= minimizeBtnX + BUTTON_WIDTH) then
          begin
            // Свернуть окно (пока просто скрываем)
            XUnmapWindow(display, focusedWin);
          end
          else if (x >= maximizeBtnX) and (x <= maximizeBtnX + BUTTON_WIDTH) then
          begin
            // Развернуть окно (пока просто меняем размер)
            XResizeWindow(display, focusedWin, 800, 600);
          end
          else
          begin
            // Начало перемещения окна
            isMoving := True;
            moveStartX := event.xbutton.x_root - attr.x;
            moveStartY := event.xbutton.y_root - attr.y;
          end;
        end
        else if (x >= attr.width - RESIZE_HANDLE_SIZE) and (y >= attr.height - RESIZE_HANDLE_SIZE) then
        begin
          // Начало изменения размера окна
          isResizing := True;
          resizeStartX := event.xbutton.x_root;
          resizeStartY := event.xbutton.y_root;
          initialWidth := attr.width;
          initialHeight := attr.height;
        end;
      end;
    ButtonRelease:
      begin
        isMoving := False;
        isResizing := False;
      end;
    MotionNotify:
      begin
        if isMoving then
        begin
          // Перемещение окна
          newX := event.xmotion.x_root - moveStartX;
          newY := event.xmotion.y_root - moveStartY;
          XMoveWindow(display, focusedWin, newX, newY);
        end
        else if isResizing then
        begin
          // Изменение размера окна
          newWidth := initialWidth + (event.xmotion.x_root - resizeStartX);
          newHeight := initialHeight + (event.xmotion.y_root - resizeStartY);
          XResizeWindow(display, focusedWin, newWidth, newHeight);
        end;
      end;
    KeyPress:
      begin
        if event.xkey.keycode = XKeysymToKeycode(display, XK_Q) then
          Halt
        else if event.xkey.keycode = XKeysymToKeycode(display, XK_Tab) then
          FocusNextWindow;
      end;
  end;
end;

begin
  display := XOpenDisplay(nil);
  if display = nil then Halt(1);
  root := XDefaultRootWindow(display);
  XSelectInput(display, root, SubstructureRedirectMask or SubstructureNotifyMask);

  while True do
  begin
    XNextEvent(display, @event);
    HandleEvent;
  end;

  XCloseDisplay(display);
end.