Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add borderless windows for Windows and Linux X11 #497

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ pub struct Conf {
///
/// Default: false
pub fullscreen: bool,
/// Whether the window should be created without borders, ignored on wasm/android.
///
/// Default: false
pub borderless: bool,
/// MSAA sample count
///
/// Default: 1
Expand Down Expand Up @@ -221,6 +225,7 @@ impl Default for Conf {
window_height: 600,
high_dpi: false,
fullscreen: false,
borderless: false,
sample_count: 1,
window_resizable: true,
icon: Some(Icon::miniquad_logo()),
Expand All @@ -238,6 +243,7 @@ impl Default for Conf {
window_height: 600,
high_dpi: true,
fullscreen: true,
borderless: false,
sample_count: 1,
window_resizable: false,
icon: Some(Icon::miniquad_logo()),
Expand Down
7 changes: 7 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,13 @@ pub mod window {
.unwrap();
}

pub fn set_borderless(borderless: bool) {
let d = native_display().lock().unwrap();
d.native_requests
.send(native::Request::SetBorderless(borderless))
.unwrap();
}

/// Get current OS clipboard value
pub fn clipboard_get() -> Option<String> {
let mut d = native_display().lock().unwrap();
Expand Down
1 change: 1 addition & 0 deletions src/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ pub(crate) enum Request {
SetWindowSize { new_width: u32, new_height: u32 },
SetWindowPosition { new_x: u32, new_y: u32 },
SetFullscreen(bool),
SetBorderless(bool),
ShowKeyboard(bool),
}

Expand Down
31 changes: 30 additions & 1 deletion src/native/linux_x11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{

use libx11::*;

use std::collections::HashMap;
use std::{collections::HashMap, mem};

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum X11Error {
Expand Down Expand Up @@ -261,6 +261,31 @@ impl X11Display {
}
}

unsafe fn set_borderless(&mut self, window: Window, borderless: bool) {
let hints_atom = (self.libx11.XInternAtom)(
self.display,
b"_MOTIF_WM_HINTS\x00" as *const u8 as *const _,
false as _,
);

let mut hints: MWMHints = mem::zeroed();

hints.flags = 2; // MWM_HINTS_DECORATIONS
hints.decorations = if borderless { 0 } else { 1 };

(self.libx11.XChangeProperty)(
self.display,
window,
hints_atom as _,
hints_atom as _,
32,
PropModeReplace,
&mut hints as *mut _ as *mut _,
5,
);
(self.libx11.XFlush)(self.display);
}

unsafe fn set_window_size(&mut self, window: Window, new_width: i32, new_height: i32) {
(self.libx11.XResizeWindow)(self.display, window, new_width, new_height);
(self.libx11.XFlush)(self.display);
Expand Down Expand Up @@ -359,6 +384,7 @@ impl X11Display {
self.set_window_position(self.window, new_x as _, new_y as _)
}
SetFullscreen(fullscreen) => self.set_fullscreen(self.window, fullscreen),
SetBorderless(borderless) => self.set_borderless(self.window, borderless),
ShowKeyboard(..) => {
eprintln!("Not implemented for X11")
}
Expand Down Expand Up @@ -419,6 +445,9 @@ where
if conf.fullscreen {
display.set_fullscreen(display.window, true);
}
if conf.borderless {
display.set_borderless(display.window, true);
}

let mut event_handler = (f.take().unwrap())();

Expand Down
9 changes: 9 additions & 0 deletions src/native/linux_x11/libx11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,15 @@ pub mod Xutil_h {
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct MWMHints {
pub flags: libc::c_ulong,
pub functions: libc::c_ulong,
pub decorations: libc::c_ulong,
pub input_mode: libc::c_long,
pub status: libc::c_ulong,
}
#[derive(Copy, Clone)]
#[repr(C)]
pub struct XWMHints {
pub flags: libc::c_long,
pub input: libc::c_int,
Expand Down
52 changes: 33 additions & 19 deletions src/native/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

pub(crate) struct WindowsDisplay {
fullscreen: bool,
borderless: bool,
dpi_aware: bool,
window_resizable: bool,
cursor_grabbed: bool,
Expand Down Expand Up @@ -104,7 +105,7 @@
rect.right = (rect.left + new_width as i32) as _;
rect.top = (rect.bottom - new_height as i32) as _;

let win_style = get_win_style(self.fullscreen, self.window_resizable);
let win_style = get_win_style(self.fullscreen, self.borderless, self.window_resizable);
let win_style_ex: DWORD = unsafe { GetWindowLongA(self.wnd, GWL_EXSTYLE) as _ };
if unsafe {
AdjustWindowRectEx(
Expand Down Expand Up @@ -155,12 +156,13 @@
fn set_fullscreen(&mut self, fullscreen: bool) {
self.fullscreen = fullscreen as _;

let win_style: DWORD = get_win_style(self.fullscreen, self.window_resizable);
let win_style: DWORD =
get_win_style(self.fullscreen, self.borderless, self.window_resizable);

unsafe {
#[cfg(target_arch = "x86_64")]
SetWindowLongPtrA(self.wnd, GWL_STYLE, win_style as _);
#[cfg(target_arch = "i686")]

Check warning on line 165 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, x86_64-pc-windows-gnu)

unexpected `cfg` condition value: `i686`

Check warning on line 165 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (windows-latest, x86_64-pc-windows-msvc)

unexpected `cfg` condition value: `i686`
SetWindowLong(self.wnd, GWL_STYLE, win_style as _);

if self.fullscreen {
Expand Down Expand Up @@ -194,14 +196,35 @@
ShowWindow(self.wnd, SW_SHOW);
};
}

fn set_borderless(&mut self, borderless: bool) {
self.borderless = borderless as _;

let win_style: DWORD =
get_win_style(self.fullscreen, self.borderless, self.window_resizable);

unsafe {
#[cfg(target_arch = "x86_64")]
SetWindowLongPtrA(self.wnd, GWL_STYLE, win_style as _);
#[cfg(target_arch = "i686")]

Check warning on line 209 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, x86_64-pc-windows-gnu)

unexpected `cfg` condition value: `i686`

Check warning on line 209 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (windows-latest, x86_64-pc-windows-msvc)

unexpected `cfg` condition value: `i686`
SetWindowLong(self.wnd, GWL_STYLE, win_style as _);

ShowWindow(self.wnd, SW_SHOW);
};
}
}

fn get_win_style(is_fullscreen: bool, is_resizable: bool) -> DWORD {
fn get_win_style(is_fullscreen: bool, is_borderless: bool, is_resizable: bool) -> DWORD {
if is_fullscreen {
WS_POPUP | WS_SYSMENU | WS_VISIBLE
} else {
let mut win_style: DWORD =
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
let mut win_style: DWORD = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU | WS_MINIMIZEBOX;

if !is_borderless {
win_style |= WS_CAPTION;
} else {
win_style |= WS_POPUP;
}

if is_resizable {
win_style |= WS_MAXIMIZEBOX | WS_SIZEBOX;
Expand Down Expand Up @@ -606,6 +629,7 @@
unsafe fn create_window(
window_title: &str,
fullscreen: bool,
borderless: bool,
resizable: bool,
width: i32,
height: i32,
Expand All @@ -623,7 +647,7 @@
wndclassw.cbWndExtra = std::mem::size_of::<*mut std::ffi::c_void>() as i32;
RegisterClassW(&wndclassw);

let win_style: DWORD;
let win_style: DWORD = get_win_style(fullscreen, borderless, resizable);
let win_ex_style: DWORD = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
let mut rect = RECT {
left: 0,
Expand All @@ -633,22 +657,9 @@
};

if fullscreen {
win_style = WS_POPUP | WS_SYSMENU | WS_VISIBLE;
rect.right = GetSystemMetrics(SM_CXSCREEN);
rect.bottom = GetSystemMetrics(SM_CYSCREEN);
} else {
win_style = if resizable {
WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_SIZEBOX
} else {
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
};

rect.right = width;
rect.bottom = height;
}
Expand Down Expand Up @@ -824,7 +835,7 @@

fn process_request(&mut self, request: Request) {
use Request::*;
unsafe {

Check warning on line 838 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, x86_64-pc-windows-gnu)

unnecessary `unsafe` block

Check warning on line 838 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (windows-latest, x86_64-pc-windows-msvc)

unnecessary `unsafe` block
match request {
ScheduleUpdate => {
self.update_requested = true;
Expand All @@ -838,7 +849,8 @@
} => self.set_window_size(new_width as _, new_height as _),
SetWindowPosition { new_x, new_y } => self.set_window_position(new_x, new_y),
SetFullscreen(fullscreen) => self.set_fullscreen(fullscreen),
SetBorderless(borderless) => self.set_borderless(borderless),
ShowKeyboard(show) => {

Check warning on line 853 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, x86_64-pc-windows-gnu)

unused variable: `show`

Check warning on line 853 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (windows-latest, x86_64-pc-windows-msvc)

unused variable: `show`
eprintln!("Not implemented for windows")
}
}
Expand All @@ -857,6 +869,7 @@
let (wnd, dc) = create_window(
&conf.window_title,
conf.fullscreen,
conf.borderless,
conf.window_resizable,
conf.window_width as _,
conf.window_height as _,
Expand All @@ -870,6 +883,7 @@
let (msg_wnd, msg_dc) = create_msg_window();
let mut display = WindowsDisplay {
fullscreen: false,
borderless: false,
dpi_aware: false,
window_resizable: conf.window_resizable,
cursor_grabbed: false,
Expand Down Expand Up @@ -917,7 +931,7 @@

#[cfg(target_arch = "x86_64")]
SetWindowLongPtrA(wnd, GWLP_USERDATA, &mut display as *mut _ as isize);
#[cfg(target_arch = "i686")]

Check warning on line 934 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (ubuntu-latest, x86_64-pc-windows-gnu)

unexpected `cfg` condition value: `i686`

Check warning on line 934 in src/native/windows.rs

View workflow job for this annotation

GitHub Actions / Build (windows-latest, x86_64-pc-windows-msvc)

unexpected `cfg` condition value: `i686`
SetWindowLong(wnd, GWLP_USERDATA, &mut display as *mut _ as isize);

let mut done = false;
Expand Down
Loading