Skip to content

Commit 65b64ad

Browse files
birhburhnot-fl3
authored andcommitted
Window icon on osx
1 parent 69c3466 commit 65b64ad

File tree

3 files changed

+84
-3
lines changed

3 files changed

+84
-3
lines changed

src/conf.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,9 @@ pub struct Conf {
153153
/// Miniquad allows to change the window icon programmatically.
154154
/// The icon will be used as
155155
/// - taskbar and titlebar icons on Windows.
156+
/// - dock and titlebar icon on MacOs.
156157
/// - TODO: favicon on HTML5
157158
/// - TODO: taskbar and titlebar(highly dependent on the WM) icons on Linux
158-
/// - TODO: dock and titlebar icon on MacOs
159159
pub icon: Option<Icon>,
160160

161161
/// Platform specific settings. Hints to OS for context creation, driver-specific

src/native/apple/frameworks.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ pub const kCGEventLeftMouseUp: u32 = 2;
158158
pub const kCGMouseEventClickState: u32 = 1;
159159
//pub const kCGEventSourceStateHIDSystemState: u32 = 1;
160160

161+
type DataReleaseCallback = unsafe extern "C" fn(info: *mut &[u8], data: *const c_void, size: usize);
162+
161163
#[link(name = "CoreGraphics", kind = "framework")]
162164
extern "C" {
163165
pub fn CGEventSourceCreate(state_id: u32) -> ObjcId;
@@ -190,7 +192,37 @@ extern "C" {
190192
pub fn CGColorCreateGenericRGB(red: f64, green: f64, blue: f64, alpha: f64) -> ObjcId;
191193
pub fn CGAssociateMouseAndMouseCursorPosition(connected: bool);
192194
pub fn CGWarpMouseCursorPosition(newCursorPosition: NSPoint);
193-
}
195+
196+
pub fn CGImageCreate(
197+
width: usize,
198+
height: usize,
199+
bpc: usize,
200+
bpp: usize,
201+
bpr: usize,
202+
colorspace: *const ObjcId,
203+
bitmap_info: u32,
204+
provider: *const ObjcId,
205+
decode: *const c_void,
206+
interpolate: bool,
207+
intent: u32,
208+
) -> *const ObjcId;
209+
pub fn CGImageRelease(image: *const ObjcId);
210+
211+
pub fn CGDataProviderCreateWithData(
212+
info: *mut &[u8],
213+
data: *const u8,
214+
size: usize,
215+
callback: DataReleaseCallback,
216+
) -> *const ObjcId;
217+
pub fn CGDataProviderRelease(provider: *const ObjcId);
218+
219+
pub fn CGColorSpaceCreateDeviceRGB() -> *const ObjcId;
220+
pub fn CGColorSpaceRelease(space: *const ObjcId);
221+
}
222+
223+
pub const kCGBitmapByteOrderDefault: u32 = (0 << 12);
224+
pub const kCGImageAlphaLast: u32 = 3;
225+
pub const kCGRenderingIntentDefault: u32 = 0;
194226

195227
#[link(name = "Metal", kind = "framework")]
196228
extern "C" {

src/native/macos.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//!
55
use {
66
crate::{
7-
conf::AppleGfxApi,
7+
conf::{AppleGfxApi, Icon},
88
event::{EventHandler, MouseButton},
99
native::{
1010
apple::{apple_util::*, frameworks::*},
@@ -864,6 +864,51 @@ impl crate::native::Clipboard for MacosClipboard {
864864
fn set(&mut self, _data: &str) {}
865865
}
866866

867+
unsafe extern "C" fn release_data(info: *mut &[u8], _: *const c_void, _: usize) {
868+
Box::from_raw(info);
869+
}
870+
871+
unsafe fn set_icon(ns_app: ObjcId, icon: &Icon) {
872+
let width = 64 as usize;
873+
let height = 64 as usize;
874+
let colors = &icon.big[..];
875+
let rgb = CGColorSpaceCreateDeviceRGB();
876+
let bits_per_component: usize = 8; // number of bits in UInt8
877+
let bits_per_pixel = 4 * bits_per_component; // ARGB uses 4 components
878+
let bytes_per_row = width * 4; // bitsPerRow / 8
879+
880+
let data = colors.as_ptr();
881+
let size = colors.len();
882+
let boxed = Box::new(colors);
883+
let info = Box::into_raw(boxed);
884+
let provider = CGDataProviderCreateWithData(info, data, size, release_data);
885+
let image = CGImageCreate(
886+
width,
887+
height,
888+
bits_per_component,
889+
bits_per_pixel,
890+
bytes_per_row,
891+
rgb,
892+
kCGBitmapByteOrderDefault | kCGImageAlphaLast,
893+
provider,
894+
std::ptr::null(),
895+
false,
896+
kCGRenderingIntentDefault,
897+
);
898+
899+
let size = NSSize {
900+
width: width as f64,
901+
height: height as f64,
902+
};
903+
let ns_image: ObjcId = msg_send![class!(NSImage), alloc];
904+
let () = msg_send![ns_image, initWithCGImage: image size: size];
905+
906+
let () = msg_send![ns_app, setApplicationIconImage: ns_image];
907+
CGDataProviderRelease(provider);
908+
CGColorSpaceRelease(rgb);
909+
CGImageRelease(image);
910+
}
911+
867912
pub unsafe fn run<F>(conf: crate::conf::Conf, f: F)
868913
where
869914
F: 'static + FnOnce() -> Box<dyn EventHandler>,
@@ -903,6 +948,10 @@ where
903948
];
904949
let () = msg_send![ns_app, activateIgnoringOtherApps: YES];
905950

951+
if let Some(icon) = &conf.icon {
952+
set_icon(ns_app, icon);
953+
}
954+
906955
let window_masks = NSWindowStyleMask::NSTitledWindowMask as u64
907956
| NSWindowStyleMask::NSClosableWindowMask as u64
908957
| NSWindowStyleMask::NSMiniaturizableWindowMask as u64

0 commit comments

Comments
 (0)