Hai Vấn Đề Nhỏ Trong Lập Trình X Window
So với Windows, hệ thống X Window thực ra dễ hiểu hơn nhiều và có thiết kế hợp lý hơn. Tuy nhiên, tài liệu hướng dẫn về nó thì vô cùng khan hiếm, đặc biệt là tài liệu bằng tiếng Trung. Tìm kiếm mãi chỉ thấy vài bài viết lác đác, sách chuyên môn cũng gần như không thấy :( Vì vậy với tôi, lập trình trên nền X Window vất vả hơn nhiều so với Windows.
Gần đây tôi gặp không ít vấn đề, trong đó có hai vấn đề đã giải quyết xong, xin ghi lại để chia sẻ:
Bắt tín hiệu đóng cửa sổ
Trên Windows thì đơn giản, chỉ cần xử lý thông báo WM_CLOSE
. Đa số trường hợp, tín hiệu này không phải do hệ thống GUI gửi trực tiếp đến cửa sổ của bạn, mà thường là do explorer chuyển tiếp. Ngay cả khi tiến trình cửa sổ của bạn bị kẹt trong vòng lặp vô hạn không xử lý được thông báo, nút “X” trên thanh tiêu đề vẫn hoạt động bình thường.
Trong X Window, tôi nghĩ đơn giản là chỉ cần dùng sự kiện DestroyNotiify
theo tài liệu hướng dẫn. Tuy nhiên dù thêm vào vòng lặp xử lý sự kiện thế nào cũng không kích hoạt được. Thao tác nhấp chuột vào nút “X” góc trên bên phải cửa sổ sẽ đưa ra hộp thoại cảnh báo, sau khi nhấn OK sẽ buộc đóng cửa sổ - tương tự như trường hợp cửa sổ Windows bị treo.
Hóa ra cần thực hiện các bước sau:
- Dùng
XInternAtom
để lấy atomWM_DELETE_WINDOW
- Gọi
XSetWMProtocols
để đăng ký atom này cho cửa sổ - Trong vòng lặp sự kiện, xử lý phần
ClientMessage
để kiểm tra atom này, từ đó phát hiện yêu cầu đóng cửa sổ.
Khác biệt trong xử lý tự động lặp phím giữa X Window và Windows
Khi giữ phím lâu, cả hai hệ điều hành đều mô phỏng chuỗi phím lặp. Nhưng khác biệt nằm ở chỗ: X Window tự động phát sinh cả thông báo KeyRelease
(trên Windows chỉ có duy nhất một WM_KEYUP
khi nhả phím).
Trên X Window, bạn sẽ nhận được chuỗi liên tiếp các cặp KeyPress
/KeyRelease
. Về mặt logic, cách xử lý này hợp lý hơn, nhưng lại gây khó khăn cho lập trình game - vì không thể đơn giản xác định người dùng có đang giữ phím hay không.
Tôi đã từng gặp vấn đề này từ lâu. Nhờ tìm kiếm tài liệu lúc đó mới biết có thể tắt chức năng tự động lặp phím trong giao thức X. Tuy nhiên hôm nay khi muốn bổ sung phần code này, tìm kiếm mãi không thấy :( (Chết tiệt, google.cn không lưu lịch sử tìm kiếm của tôi!).
Cuối cùng phát hiện ra hai giải pháp từ tài liệu chính thức:
XAutoRepeatOn
/XAutoRepeatOff
: Tuy nhiên thao tác này ảnh hưởng toàn cục, thậm chí còn duy trì sau khi ứng dụng đóng lại.- Giải pháp tối ưu: Sử dụng
XQueryKeymap
để kiểm tra trạng thái thực tế của bàn phím. Chỉ cần gọi hàm này khi xử lý sự kiệnKeyRelease
để xác định phím có thực sự đang bị giữ hay không.
P/s: Có ai là cao thủ X Window không? Tự mày mò một mình thật sự rất bế tắc.