Skip to content

Commit

Permalink
Window icon on osx
Browse files Browse the repository at this point in the history
  • Loading branch information
birhburh authored and not-fl3 committed Apr 30, 2024
1 parent 69c3466 commit 65b64ad
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,9 @@ pub struct Conf {
/// Miniquad allows to change the window icon programmatically.
/// The icon will be used as
/// - taskbar and titlebar icons on Windows.
/// - dock and titlebar icon on MacOs.
/// - TODO: favicon on HTML5
/// - TODO: taskbar and titlebar(highly dependent on the WM) icons on Linux
/// - TODO: dock and titlebar icon on MacOs
pub icon: Option<Icon>,

/// Platform specific settings. Hints to OS for context creation, driver-specific
Expand Down
34 changes: 33 additions & 1 deletion src/native/apple/frameworks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ pub const kCGEventLeftMouseUp: u32 = 2;
pub const kCGMouseEventClickState: u32 = 1;
//pub const kCGEventSourceStateHIDSystemState: u32 = 1;

type DataReleaseCallback = unsafe extern "C" fn(info: *mut &[u8], data: *const c_void, size: usize);

#[link(name = "CoreGraphics", kind = "framework")]
extern "C" {
pub fn CGEventSourceCreate(state_id: u32) -> ObjcId;
Expand Down Expand Up @@ -190,7 +192,37 @@ extern "C" {
pub fn CGColorCreateGenericRGB(red: f64, green: f64, blue: f64, alpha: f64) -> ObjcId;
pub fn CGAssociateMouseAndMouseCursorPosition(connected: bool);
pub fn CGWarpMouseCursorPosition(newCursorPosition: NSPoint);
}

pub fn CGImageCreate(
width: usize,
height: usize,
bpc: usize,
bpp: usize,
bpr: usize,
colorspace: *const ObjcId,
bitmap_info: u32,
provider: *const ObjcId,
decode: *const c_void,
interpolate: bool,
intent: u32,
) -> *const ObjcId;
pub fn CGImageRelease(image: *const ObjcId);

pub fn CGDataProviderCreateWithData(
info: *mut &[u8],
data: *const u8,
size: usize,
callback: DataReleaseCallback,
) -> *const ObjcId;
pub fn CGDataProviderRelease(provider: *const ObjcId);

pub fn CGColorSpaceCreateDeviceRGB() -> *const ObjcId;
pub fn CGColorSpaceRelease(space: *const ObjcId);
}

pub const kCGBitmapByteOrderDefault: u32 = (0 << 12);
pub const kCGImageAlphaLast: u32 = 3;
pub const kCGRenderingIntentDefault: u32 = 0;

#[link(name = "Metal", kind = "framework")]
extern "C" {
Expand Down
51 changes: 50 additions & 1 deletion src/native/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//!
use {
crate::{
conf::AppleGfxApi,
conf::{AppleGfxApi, Icon},
event::{EventHandler, MouseButton},
native::{
apple::{apple_util::*, frameworks::*},
Expand Down Expand Up @@ -864,6 +864,51 @@ impl crate::native::Clipboard for MacosClipboard {
fn set(&mut self, _data: &str) {}
}

unsafe extern "C" fn release_data(info: *mut &[u8], _: *const c_void, _: usize) {
Box::from_raw(info);
}

unsafe fn set_icon(ns_app: ObjcId, icon: &Icon) {
let width = 64 as usize;
let height = 64 as usize;
let colors = &icon.big[..];
let rgb = CGColorSpaceCreateDeviceRGB();
let bits_per_component: usize = 8; // number of bits in UInt8
let bits_per_pixel = 4 * bits_per_component; // ARGB uses 4 components
let bytes_per_row = width * 4; // bitsPerRow / 8

let data = colors.as_ptr();
let size = colors.len();
let boxed = Box::new(colors);
let info = Box::into_raw(boxed);
let provider = CGDataProviderCreateWithData(info, data, size, release_data);
let image = CGImageCreate(
width,
height,
bits_per_component,
bits_per_pixel,
bytes_per_row,
rgb,
kCGBitmapByteOrderDefault | kCGImageAlphaLast,
provider,
std::ptr::null(),
false,
kCGRenderingIntentDefault,
);

let size = NSSize {
width: width as f64,
height: height as f64,
};
let ns_image: ObjcId = msg_send![class!(NSImage), alloc];
let () = msg_send![ns_image, initWithCGImage: image size: size];

let () = msg_send![ns_app, setApplicationIconImage: ns_image];
CGDataProviderRelease(provider);
CGColorSpaceRelease(rgb);
CGImageRelease(image);
}

pub unsafe fn run<F>(conf: crate::conf::Conf, f: F)
where
F: 'static + FnOnce() -> Box<dyn EventHandler>,
Expand Down Expand Up @@ -903,6 +948,10 @@ where
];
let () = msg_send![ns_app, activateIgnoringOtherApps: YES];

if let Some(icon) = &conf.icon {
set_icon(ns_app, icon);
}

let window_masks = NSWindowStyleMask::NSTitledWindowMask as u64
| NSWindowStyleMask::NSClosableWindowMask as u64
| NSWindowStyleMask::NSMiniaturizableWindowMask as u64
Expand Down

0 comments on commit 65b64ad

Please sign in to comment.