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:
Elias Naur
2019-07-21 16:53:44 +02:00
parent cb59594b5b
commit 8eea6b80f3
4 changed files with 43 additions and 21 deletions
+1 -1
View File
@@ -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
View File
@@ -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))
+2
View File
@@ -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
View File
@@ -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 |