Electron 창을 드래그 가능하게 만들고 Mouse Enter/Leave 감지를 유지하는 방법

발행: (2025년 12월 3일 오후 09:41 GMT+9)
4 min read
원문: Dev.to

Source: Dev.to

소개

앱을 완전히 드래그 가능하게 하면서 마우스 enter와 leave 시 높이와 너비를 변경하고 싶었습니다. 기본적으로 창을 드래그 가능하게 하면 드래그 영역에서 마우스 이벤트가 무시되기 때문에 일반적인 enter/leave 감지가 깨집니다.

시각적 비교

마우스가 밖에 있을 때

Focus app widget mouse outside

마우스가 안에 있을 때

Focus app widget mouse inside

창 설정

const mainWindow = new BrowserWindow({
  // width, height, x, y, etc.
  titleBarStyle: 'hidden',
  backgroundMaterial: "acrylic",
  visualEffectState: "active",
  vibrancy: "popover", // macOS
  frame: false, // frameless window
});

창을 드래그 가능하게 만들기

드래그 영역으로 사용할 모든 영역에 다음 클래스를 추가합니다:

.dragAble {
  -webkit-user-select: none;
  -webkit-app-region: drag;
}

상호작용이 필요하도록 유지해야 하는 요소는 다음을 사용합니다:

.no-drag {
  -webkit-app-region: no-drag;
}

마우스 enter와 leave 처리

Electron은 전체 창에 대한 네이티브 mouse‑enter/leave 이벤트를 제공하지 않으므로 직접 구현합니다.

1. 폴링 리스너

유틸리티가 일정 간격으로 실행되어 커서 위치를 창 경계와 비교하고 결과를 콜백에 전달합니다.

function listenToMouseMovement(callback) {
  const id = setInterval(() => {
    const cursor = screen.getCursorScreenPoint();
    const bounds = esm.mainWindow.getBounds();

    const inside =
      cursor.x >= bounds.x &&
      cursor.x = bounds.y &&
      cursor.y  {
  if (esm.isMovingWindow) return; // ignore while dragging

  if (inside) {
    // Cancel any pending leave timeout
    if (leaveTimeout) {
      clearTimeout(leaveTimeout);
      leaveTimeout = null;
    }

    if (esm.mouseWasOutsideWindow) {
      // Debounce the enter event
      if (!enterTimeout) {
        enterTimeout = setTimeout(() => {
          esm.mouseWasOutsideWindow = false;
          mainWindow.webContents.send("onMouseIsInsideTheApp");
        }, 120);
      }
    }
  } else {
    // Cancel any pending enter timeout
    if (enterTimeout) {
      clearTimeout(enterTimeout);
      enterTimeout = null;
    }

    if (!esm.mouseWasOutsideWindow) {
      // Debounce the leave event
      if (!leaveTimeout) {
        leaveTimeout = setTimeout(() => {
          esm.mouseWasOutsideWindow = true;
          mainWindow.webContents.send("onMouseIsOutsideTheApp");
        }, 120);
      }
    }
  }
});

3. 창이 이동 중일 때 마우스 체크 무시하기

Electron의 네이티브 이벤트를 사용해 창의 이동 상태를 추적합니다:

esm.mainWindow.on("will-move", () => {
  esm.isMovingWindow = true;
});

esm.mainWindow.on("move", () => {
  esm.isMovingWindow = true;
  if (esm.moveEndTimeout) {
    clearTimeout(esm.moveEndTimeout);
    esm.moveEndTimeout = null;
  }
});

esm.mainWindow.on("moved", () => {
  if (esm.moveEndTimeout) clearTimeout(esm.moveEndTimeout);
  esm.moveEndTimeout = setTimeout(() => {
    esm.isMovingWindow = false;
    esm.moveEndTimeout = null;
  }, 200);
});

결과

이 방법은 깜빡임을 없애고 창을 완전히 드래그 가능하게 하면서도 마우스 enter와 leave 이벤트에 반응하도록 합니다. 동작 예시는 이 트윗에서 확인할 수 있습니다: (링크는 생략)

읽어 주셔서 감사합니다! 첫 번째 글이며, 앞으로 더 많은 글을 올릴 예정입니다.

Back to Blog

관련 글

더 보기 »

JavaScript 첫 걸음: 간단한 정리

JavaScript에서 변수 let: 나중에 값이 변경될 수 있는 경우에 사용합니다. 예시: ```javascript let age = 20; age = 21; ``` const: 값이 절대로 변경되지 않아야 할 때 사용합니다.