0011 최대화한 창이 원래 크기로 돌아오지 않음
Super + 위로 최대화한 다음 Super + 아래를 눌러도 창이 꿈쩍도 하지 않습니다. GNOME 쪽은 최대화를 푼 것으로 알고 있고, 창만 큰 채로 남습니다.
추적을 켜고 두 번 눌러보면 이렇게 나옵니다.
xdg_toplevel_handle_configure hwnd=0x10078 1920x1048,0x5 ← 최대화
wayland_configure_window processing=1920x1048,0x5
wayland_surface_update_state_toplevel window_state=0x1
xdg_toplevel_handle_configure hwnd=0x10078 960x1048,0 ← 최대화 해제
wayland_configure_window processing=0x0,0
wayland_surface_update_state_toplevel window_state=0
컴포지터는 960x1048을 또박또박 보내주는데 드라이버 쪽에서는
0x0이 됩니다. 일부러 그렇게 합니다. 최대화나 전체화면처럼
크기를 꼭 지켜야 하는 상태가 아니면 configure에 실린 크기는 권고일 뿐이라,
wayland_configure_window가 버립니다.
if (state)
{
width = surface->processing.rect.right - surface->processing.rect.left;
height = surface->processing.rect.bottom - surface->processing.rect.top;
}
else
{
width = height = 0;
}
여기까지는 맞습니다. 문제는 그 다음입니다. 상태가 바뀐 것은 반영해야 하니
WS_MAXIMIZE를 손으로 떼는데, 크기는 0이라 같이 붙는
SetWindowPos는 SWP_NOSIZE로 아무것도 안 합니다.
NtUserSetWindowLong(hwnd, GWL_STYLE, style ^ WS_MAXIMIZE, FALSE);
그래서 스타일 비트만 떨어지고 창은 최대화된 크기 그대로입니다. 게다가 이제 원래 크기를 기억하는 곳이 아무 데도 없습니다. 컴포지터는 자기가 보낸 크기가 반영되지 않으니 같은 configure를 계속 다시 보내고, 로그가 몇 초에 한 번씩 같은 줄로 채워집니다.
원래 크기는 Win32가 압니다. 창을 최대화할 때 normal placement를 저장해
두니까요. 그래서 비트를 손으로 떼는 대신 SC_RESTORE를 보내
Win32에게 복원을 맡겼습니다. 바로 위에 있는 최소화 복원이 이미 같은
방식입니다.
TRACE("hwnd=%p restoring from maximize\n", hwnd);
surface->current = surface->processing;
memset(&surface->processing, 0, sizeof(surface->processing));
xdg_surface_ack_configure(surface->xdg_surface, surface->current.serial);
wayland_win_data_release(data);
send_message(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
configure를 먼저 ack하는 것은 프로토콜 위반을 피하려는 것이고,
SC_RESTORE가 창을 줄이면 그때 configure 주기가 새로
돕니다.
최소화된 창은 건드리지 않습니다. 최소화하기 전에 최대화돼 있던 창은
WS_MAXIMIZE와 WS_MINIMIZE를 함께 가지고
있어서, 여기서 복원을 보내면 사용자가 내려둔 창이 혼자 올라옵니다.