mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-05 09:25:38 +00:00
ui/app: (macOS) use a consistent and constant backing store constant
Compute and keep constant the pixel density, to avoid window content changes when moving to another monitor with a different density. Use backing store scale, not content scale for input events. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+1
-1
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
static void handleMouse(NSView *view, NSEvent *event, int typ, CGFloat dx, CGFloat dy) {
|
static void handleMouse(NSView *view, NSEvent *event, int typ, CGFloat dx, CGFloat dy) {
|
||||||
NSPoint p = [view convertPoint:[event locationInWindow] fromView:nil];
|
NSPoint p = [view convertPoint:[event locationInWindow] fromView:nil];
|
||||||
CGFloat scale = view.layer.contentsScale;
|
CGFloat scale = view.window.backingScaleFactor;
|
||||||
if (!event.hasPreciseScrollingDeltas) {
|
if (!event.hasPreciseScrollingDeltas) {
|
||||||
// dx and dy are in rows and columns.
|
// dx and dy are in rows and columns.
|
||||||
dx *= 10;
|
dx *= 10;
|
||||||
|
|||||||
+22
-6
@@ -33,6 +33,7 @@ type window struct {
|
|||||||
view C.CFTypeRef
|
view C.CFTypeRef
|
||||||
w *Window
|
w *Window
|
||||||
stage Stage
|
stage Stage
|
||||||
|
ppdp float32
|
||||||
}
|
}
|
||||||
|
|
||||||
type viewCmd struct {
|
type viewCmd struct {
|
||||||
@@ -183,11 +184,14 @@ func gio_onFocus(view C.CFTypeRef, focus C.BOOL) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) draw(sync bool) {
|
func (w *window) draw(sync bool) {
|
||||||
width, height := int(C.gio_viewWidth(w.view)+.5), int(C.gio_viewHeight(w.view)+.5)
|
wf, hf := float32(C.gio_viewWidth(w.view)), float32(C.gio_viewHeight(w.view))
|
||||||
if width == 0 || height == 0 {
|
if wf == 0 || hf == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cfg := getConfig()
|
scale := float32(C.gio_getViewBackingScale(w.view))
|
||||||
|
width := int(wf*scale + .5)
|
||||||
|
height := int(hf*scale + .5)
|
||||||
|
cfg := configFor(w.ppdp, scale)
|
||||||
cfg.now = time.Now()
|
cfg.now = time.Now()
|
||||||
w.setStage(StageRunning)
|
w.setStage(StageRunning)
|
||||||
w.w.event(DrawEvent{
|
w.w.event(DrawEvent{
|
||||||
@@ -200,12 +204,17 @@ func (w *window) draw(sync bool) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func getConfig() Config {
|
func getPixelsPerDp(scale float32) float32 {
|
||||||
ppdp := float32(C.gio_getPixelsPerDP())
|
ppdp := float32(C.gio_getPixelsPerDP())
|
||||||
ppdp *= monitorScale
|
ppdp = ppdp * scale * monitorScale
|
||||||
if ppdp < minDensity {
|
if ppdp < minDensity {
|
||||||
ppdp = minDensity
|
ppdp = minDensity
|
||||||
}
|
}
|
||||||
|
return ppdp / scale
|
||||||
|
}
|
||||||
|
|
||||||
|
func configFor(ppdp, scale float32) Config {
|
||||||
|
ppdp = ppdp * scale
|
||||||
return Config{
|
return Config{
|
||||||
pxPerDp: ppdp,
|
pxPerDp: ppdp,
|
||||||
pxPerSp: ppdp,
|
pxPerSp: ppdp,
|
||||||
@@ -240,8 +249,10 @@ func gio_onShow(view C.CFTypeRef) {
|
|||||||
//export gio_onCreate
|
//export gio_onCreate
|
||||||
func gio_onCreate(view C.CFTypeRef) {
|
func gio_onCreate(view C.CFTypeRef) {
|
||||||
viewDo(view, func(views viewMap, view C.CFTypeRef) {
|
viewDo(view, func(views viewMap, view C.CFTypeRef) {
|
||||||
|
scale := float32(C.gio_getBackingScale())
|
||||||
w := &window{
|
w := &window{
|
||||||
view: view,
|
view: view,
|
||||||
|
ppdp: getPixelsPerDp(scale),
|
||||||
}
|
}
|
||||||
wopts := <-mainWindow.out
|
wopts := <-mainWindow.out
|
||||||
w.w = wopts.window
|
w.w = wopts.window
|
||||||
@@ -262,10 +273,15 @@ func Main() {
|
|||||||
// TODO: return this error from CreateWindow.
|
// TODO: return this error from CreateWindow.
|
||||||
panic(errors.New("CreateWindow: failed to create view"))
|
panic(errors.New("CreateWindow: failed to create view"))
|
||||||
}
|
}
|
||||||
cfg := getConfig()
|
scale := float32(C.gio_getBackingScale())
|
||||||
|
ppdp := getPixelsPerDp(scale)
|
||||||
|
cfg := configFor(ppdp, scale)
|
||||||
opts := wopts.opts
|
opts := wopts.opts
|
||||||
w := cfg.Px(opts.Width)
|
w := cfg.Px(opts.Width)
|
||||||
h := cfg.Px(opts.Height)
|
h := cfg.Px(opts.Height)
|
||||||
|
// Window sizes is on screen coordinates, not device pixels.
|
||||||
|
w = int(float32(w) / scale)
|
||||||
|
h = int(float32(h) / scale)
|
||||||
title := C.CString(opts.Title)
|
title := C.CString(opts.Title)
|
||||||
defer C.free(unsafe.Pointer(title))
|
defer C.free(unsafe.Pointer(title))
|
||||||
C.gio_main(view, title, C.CGFloat(w), C.CGFloat(h))
|
C.gio_main(view, title, C.CGFloat(w), C.CGFloat(h))
|
||||||
|
|||||||
@@ -13,5 +13,7 @@ __attribute__ ((visibility ("hidden"))) CGFloat gio_viewHeight(CFTypeRef viewRef
|
|||||||
__attribute__ ((visibility ("hidden"))) void gio_setAnimating(CFTypeRef viewRef, BOOL anim);
|
__attribute__ ((visibility ("hidden"))) void gio_setAnimating(CFTypeRef viewRef, BOOL anim);
|
||||||
__attribute__ ((visibility ("hidden"))) void gio_updateDisplayLink(CFTypeRef viewRef, CGDirectDisplayID dispID);
|
__attribute__ ((visibility ("hidden"))) void gio_updateDisplayLink(CFTypeRef viewRef, CGDirectDisplayID dispID);
|
||||||
__attribute__ ((visibility ("hidden"))) CGFloat gio_getPixelsPerDP(void);
|
__attribute__ ((visibility ("hidden"))) CGFloat gio_getPixelsPerDP(void);
|
||||||
|
__attribute__ ((visibility ("hidden"))) CGFloat gio_getBackingScale(void);
|
||||||
|
__attribute__ ((visibility ("hidden"))) CGFloat gio_getViewBackingScale(CFTypeRef viewRef);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+18
-14
@@ -13,8 +13,8 @@
|
|||||||
|
|
||||||
@implementation GioDelegate
|
@implementation GioDelegate
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||||
[[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)];
|
[[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)];
|
||||||
[self.window makeKeyAndOrderFront:self];
|
[self.window makeKeyAndOrderFront:self];
|
||||||
gio_onShow((__bridge CFTypeRef)self.window.contentView);
|
gio_onShow((__bridge CFTypeRef)self.window.contentView);
|
||||||
}
|
}
|
||||||
- (void)applicationDidHide:(NSNotification *)aNotification {
|
- (void)applicationDidHide:(NSNotification *)aNotification {
|
||||||
@@ -31,7 +31,8 @@
|
|||||||
}
|
}
|
||||||
- (void)windowDidChangeScreen:(NSNotification *)notification {
|
- (void)windowDidChangeScreen:(NSNotification *)notification {
|
||||||
CGDirectDisplayID dispID = [[[self.window screen] deviceDescription][@"NSScreenNumber"] unsignedIntValue];
|
CGDirectDisplayID dispID = [[[self.window screen] deviceDescription][@"NSScreenNumber"] unsignedIntValue];
|
||||||
gio_updateDisplayLink((__bridge CFTypeRef)self.window.contentView, dispID);
|
CFTypeRef view = (__bridge CFTypeRef)self.window.contentView;
|
||||||
|
gio_updateDisplayLink(view, dispID);
|
||||||
}
|
}
|
||||||
- (void)windowDidBecomeKey:(NSNotification *)notification {
|
- (void)windowDidBecomeKey:(NSNotification *)notification {
|
||||||
gio_onFocus((__bridge CFTypeRef)self.window.contentView, YES);
|
gio_onFocus((__bridge CFTypeRef)self.window.contentView, YES);
|
||||||
@@ -48,14 +49,12 @@
|
|||||||
|
|
||||||
CGFloat gio_viewHeight(CFTypeRef viewRef) {
|
CGFloat gio_viewHeight(CFTypeRef viewRef) {
|
||||||
NSView *view = (__bridge NSView *)viewRef;
|
NSView *view = (__bridge NSView *)viewRef;
|
||||||
NSRect bounds = [view convertRectToBacking:[view bounds]];
|
return [view bounds].size.height;
|
||||||
return bounds.size.height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CGFloat gio_viewWidth(CFTypeRef viewRef) {
|
CGFloat gio_viewWidth(CFTypeRef viewRef) {
|
||||||
NSView *view = (__bridge NSView *)viewRef;
|
NSView *view = (__bridge NSView *)viewRef;
|
||||||
NSRect bounds = [view convertRectToBacking:[view bounds]];
|
return [view bounds].size.width;
|
||||||
return bounds.size.width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Points pr. dp.
|
// Points pr. dp.
|
||||||
@@ -68,8 +67,18 @@ static CGFloat getPointsPerDP(NSScreen *screen) {
|
|||||||
|
|
||||||
// Pixels pr dp.
|
// Pixels pr dp.
|
||||||
CGFloat gio_getPixelsPerDP(void) {
|
CGFloat gio_getPixelsPerDP(void) {
|
||||||
NSScreen *screen = [NSScreen mainScreen];
|
NSScreen *screen = [NSScreen mainScreen];
|
||||||
return [screen backingScaleFactor] * getPointsPerDP(screen);
|
return getPointsPerDP(screen);
|
||||||
|
}
|
||||||
|
|
||||||
|
CGFloat gio_getBackingScale() {
|
||||||
|
NSScreen *screen = [NSScreen mainScreen];
|
||||||
|
return [screen backingScaleFactor];
|
||||||
|
}
|
||||||
|
|
||||||
|
CGFloat gio_getViewBackingScale(CFTypeRef viewRef) {
|
||||||
|
NSView *view = (__bridge NSView *)viewRef;
|
||||||
|
return [view.window backingScaleFactor];
|
||||||
}
|
}
|
||||||
|
|
||||||
void gio_main(CFTypeRef viewRef, const char *title, CGFloat width, CGFloat height) {
|
void gio_main(CFTypeRef viewRef, const char *title, CGFloat width, CGFloat height) {
|
||||||
@@ -94,11 +103,6 @@ void gio_main(CFTypeRef viewRef, const char *title, CGFloat width, CGFloat heigh
|
|||||||
[menuBar addItem:mainMenu];
|
[menuBar addItem:mainMenu];
|
||||||
[NSApp setMainMenu:menuBar];
|
[NSApp setMainMenu:menuBar];
|
||||||
|
|
||||||
// Width and height are in pixels; convert to points
|
|
||||||
CGFloat scale = [[NSScreen mainScreen] backingScaleFactor];
|
|
||||||
width /= scale;
|
|
||||||
height /= scale;
|
|
||||||
|
|
||||||
NSRect rect = NSMakeRect(0, 0, width, height);
|
NSRect rect = NSMakeRect(0, 0, width, height);
|
||||||
NSWindowStyleMask styleMask = NSWindowStyleMaskTitled |
|
NSWindowStyleMask styleMask = NSWindowStyleMaskTitled |
|
||||||
NSWindowStyleMaskResizable |
|
NSWindowStyleMaskResizable |
|
||||||
|
|||||||
Reference in New Issue
Block a user