A bit late to the party, but I just installed Big Sur on my laptop. Running my app there, I notice that my dock icon annotation appears microscopic. Is this because it still uses the old dock icons that were OK on Mojave? I never made any progress on changing that.
@Sam_Rowlands makes Iconographer which can help you quickly make a squircle Big Sur icon if you need one.
Thanks, I went that route. And running with a new .icns file for the app’s icons works as before on Mojave. But under Big Sur, my dock icon annotation is still microscopic.
And under Big Sur, can’t the IDE delete the debug app after the app terminates? I’m using remote debugging, with 2020r1.1 under Mojave.
a) screenshot
b) code
Dock animation is working fine here on Monterey. But AFAIR I had to change some code. Resetting the dock is buggy.
Here’s my code to update the icon with a red disk with a count in it. The disk is supposed to be in the top righthand corner:
// Sets the app Dock icon based on the current count of unread mails.
#if (TargetMacOS=True) then
Var iconPtr as DockItem, graphic As Graphics, mystr As String, x, y As Integer
iconPtr = App.DockItem
graphic = iconPtr.Graphics
iconPtr.ResetIcon ()
graphic.DrawPicture (ilettericon, 0, 0, 512, 512)
iconPtr.UpdateNow ()
if (unreadCount=0) then Return
graphic.DrawingColor = &cff0000
graphic.FillOval (280, 10, 220, 220)
if (unreadCount>99) Then
graphic.FontSize = 330
x = 330
y = 300
mystr = "*"
ElseIf (unreadCount>9) Then
graphic.FillOval (230, 10, 220, 220)
graphic.FontSize = 172
x = 275
y = 180
mystr = unreadCount.ToString
Else
graphic.FontSize = 172
x = 345
y = 180
mystr = unreadCount.ToString
end if
graphic.DrawingColor = &cffffff
graphic.FontName = "Helvetica"
graphic.FontUnit = FontUnits.Point
graphic.Bold = True
graphic.DrawText (mystr, x, y)
iconPtr.UpdateNow ()
Return
#endif
This code worked as expected under Mojave with a full-size rectangular 512x512 icon. Now, with the smaller masked-off icons, surrounded by a transparent area, we see:
-
Under Mojave, the red oval is drawn in the right place at the right size. However, ResetIcon() appears to do nothing, so if
unreadCount=0
then I’m left with a red rising sun behind the right shoulder of the icon. -
Under Big Sur it’s more bizarre. The same thing is drawn, same behaviour, but as a perhaps 4x4 image (still at 0, 0) rather than full-size. So the icon has a small pixel-pixie on its left shoulder.
Couple of minor points that I can see:
- DockItem.Reset doesn’t work (<https://xojo.com/issue/63498>).
- I’m not using a fixed font but a multiple of 128.
Here is my partial code for the dock badge (screenshot above is for the animation):
dim DockGraphics as Graphics = app.DockItem.Graphics
if DockGraphics = Nil then Return
dim MainPicture as new Picture(DockGraphics.Width, DockGraphics.Width, 32)
const FontSize as Integer = 28
const BaseOffSet as Integer = 14
const BaseArc as Integer = 20
'set up data for picture
dim ScaleFactor as Integer = DockGraphics.Width/128
dim theGraphics as Graphics = MainPicture.Graphics
theGraphics.FontSize = FontSize * ScaleFactor
dim theWidth as Integer = theGraphics.TextWidth(str(NoOfMailsAdded))
theWidth = Max(theWidth, MaxWidth)
MaxWidth = theWidth
dim theHeight as Integer = theGraphics.TextHeight(str(NoOfMailsAdded), 10000)
dim Offset as Integer = BaseOffSet * ScaleFactor
dim PictureOffset as Integer = MainPicture.Height - theWidth - Offset
dim theArc as Integer = BaseArc * ScaleFactor
'draw main picture
'draw background
FillRectangleGradient(theGraphics, 0, 0, theGraphics.Width, Offset + theHeight, Color.RGB(137, 22, 27), Color.RGB(184, 44, 35))
'draw number
theGraphics.DrawingColor = Color.RGB(255, 255, 255)
theGraphics.DrawText(str(NoOfMailsAdded), PictureOffset + Offset/2, Offset/2 + theGraphics.FontAscent)
'draw border
theGraphics.DrawingColor = Color.RGB(117, 0, 19)
theGraphics.PenSize = 2 * ScaleFactor
theGraphics.DrawRoundRectangle(PictureOffset, 0, Offset + theWidth, Offset + theHeight, theArc, theArc)
The full code example is attached to the Feedback case.
I wouldn’t assume that the size will be 512. Since the dawn of retina, the max size is actually 1024 and could certainly change again in the future if Apple decides to have a 3x display like on iOS.
You could just make a multiplier like this:
Var scaleFactor as double = g.width / 512
And then multiply by that number for any sizes that you need, including text.
Don’t draw your own badge.
https://developer.apple.com/documentation/appkit/nsdocktile/1524433-badgelabel
Thank you for that, @Beatrix_Willius . I didn’t study it completely but it pointed me to a couple of things such as ClearRectangle()
, and as a result, the code that was:
iconPtr = App.DockItem
graphic = iconPtr.Graphics
iconPtr.ResetIcon ()
graphic.DrawPicture (ilettericon, 0, 0, 512, 512)
iconPtr.UpdateNow ()
if (unreadCount=0) then Return
is now:
iconPtr = App.DockItem
graphic = iconPtr.Graphics
icon = new Picture (graphic.Width, graphic.Width, 32)
icon = iLettericon
graphic.ClearRectangle (0, 0, graphic.Width, graphic.Width)
graphic.DrawPicture (icon, 0, 0, graphic.Width, graphic.Width)
iconPtr.UpdateNow ()
if (unreadCount=0) then Return
and this gives the right behaviour under Mojave, with the new style icon. Under Big Sur, as soon as this method is called. I think the drawing that is done is correct, but the icon that’s drawn is only a few pixels (perhaps 16) high and wide. That replaces the normal dock icon until the app quits, So there’s a scaling issue, presumably.
What is the third parameter (32) for new Picture
?
Seriously… stop drawing it yourself. The system provides you the right way to do this. It’ll scale the badge separately from your icon so it always looks right and you don’t have to futz around with making it work.
Declare Function NSClassFromString Lib "Foundation" (className As CFStringRef) As Ptr
Var NSApp As Ptr = NSClassFromString("NSApplication")
Declare Function SharedApplication Lib "Foundation" Selector "sharedApplication" (receiver As Ptr) As Ptr
Var SharedApp As Ptr = SharedApplication(NSApp)
Declare Function DockTile Lib "Foundation" Selector "dockTile" (receiver As Ptr) As Ptr
Var Tile As Ptr = DockTile(SharedApp)
Declare Sub SetBadge Lib "Foundation" Selector "setBadgeLabel:" (receiver As Ptr, label As CFStringRef)
SetBadge(Tile, "3")
You’re also doing absolutely nothing on the first line since you’re creating a new picture to match the size of the graphics object, then immediately throwing it away. On the next lines you’re scaling iLettericon to fill the graphic
space.
But just throw out all this code and let the system manage your application icon and badge unless you’re trying to change the actual icon. Even if you’re changing the icon at runtime, don’t draw the badge.
OK, I’ll give it a try. But not tonight, it’s nearly midnght. Time for a few pages of Agatha Christie.
I have to say that the picture code did look odd, but I’ve been battling a number of issues today.
I’ve tested your declares now in Mojave and BS and it works as advertised, so thanks for that; I see that a blank string makes the badge go away, (as I’d hoped). My only question is, is there a way to make the badge’s text be bold? That would make it slightly more readable.
Funnily enough, my original code only worked under Mojave because as luck would have it I only had one icon for the app (at 512x512). Once I included a full set (from Iconographer Mini), my badge, which was displaying small under BS, started doing the same under Mojave.
Any way to change the background colour (or any font property) in this code?
No. I’d imagine since it is system-supplied that it obeys accessibility settings. So if the user’s system wants bolder text, I’d expect this badge to be bolder too. It’s not what you’re looking for, but Apple doesn’t give you options.
Same basic reply. All you can tell the system is what the badge should say. Everything else is handled for you. So if the user has colorblind options enabled, high contrast mode enabled, Apple moves the badge, makes it blink, turns it upside down, or any other crazy idea, your app will instantly match.
So if you want to notify in a non-red colour (for instance), the custom way is still mandatory.
I’d argue you shouldn’t be doing it. Go with what the user knows and expects.
For most other UI things, I’d agree. Here, red is normally a “warning” icon. I can imagine times where this isn’t appropriate (and I hate red, personally…).
Sure, but in this case it isn’t. This is the color Apple chose for its badge. It’s what the user expects.
Oh… that’s interesting and too bad