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) {
NSPoint p = [view convertPoint:[event locationInWindow] fromView:nil];
CGFloat scale = view.layer.contentsScale;
CGFloat scale = view.window.backingScaleFactor;
if (!event.hasPreciseScrollingDeltas) {
// dx and dy are in rows and columns.
dx *= 10;
+22 -6
View File
@@ -33,6 +33,7 @@ type window struct {
view C.CFTypeRef
w *Window
stage Stage
ppdp float32
}
type viewCmd struct {
@@ -183,11 +184,14 @@ func gio_onFocus(view C.CFTypeRef, focus C.BOOL) {
}
func (w *window) draw(sync bool) {
width, height := int(C.gio_viewWidth(w.view)+.5), int(C.gio_viewHeight(w.view)+.5)
if width == 0 || height == 0 {
wf, hf := float32(C.gio_viewWidth(w.view)), float32(C.gio_viewHeight(w.view))
if wf == 0 || hf == 0 {
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()
w.setStage(StageRunning)
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 *= monitorScale
ppdp = ppdp * scale * monitorScale
if ppdp < minDensity {
ppdp = minDensity
}
return ppdp / scale
}
func configFor(ppdp, scale float32) Config {
ppdp = ppdp * scale
return Config{
pxPerDp: ppdp,
pxPerSp: ppdp,
@@ -240,8 +249,10 @@ func gio_onShow(view C.CFTypeRef) {
//export gio_onCreate
func gio_onCreate(view C.CFTypeRef) {
viewDo(view, func(views viewMap, view C.CFTypeRef) {
scale := float32(C.gio_getBackingScale())
w := &window{
view: view,
ppdp: getPixelsPerDp(scale),
}
wopts := <-mainWindow.out
w.w = wopts.window
@@ -262,10 +273,15 @@ func Main() {
// TODO: return this error from CreateWindow.
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
w := cfg.Px(opts.Width)
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)
defer C.free(unsafe.Pointer(title))
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_updateDisplayLink(CFTypeRef viewRef, CGDirectDisplayID dispID);
__attribute__ ((visibility ("hidden"))) CGFloat gio_getPixelsPerDP(void);
__attribute__ ((visibility ("hidden"))) CGFloat gio_getBackingScale(void);
__attribute__ ((visibility ("hidden"))) CGFloat gio_getViewBackingScale(CFTypeRef viewRef);
#endif
+18 -14
View File
@@ -13,8 +13,8 @@
@implementation GioDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)];
[self.window makeKeyAndOrderFront:self];
[[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)];
[self.window makeKeyAndOrderFront:self];
gio_onShow((__bridge CFTypeRef)self.window.contentView);
}
- (void)applicationDidHide:(NSNotification *)aNotification {
@@ -31,7 +31,8 @@
}
- (void)windowDidChangeScreen:(NSNotification *)notification {
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 {
gio_onFocus((__bridge CFTypeRef)self.window.contentView, YES);
@@ -48,14 +49,12 @@
CGFloat gio_viewHeight(CFTypeRef viewRef) {
NSView *view = (__bridge NSView *)viewRef;
NSRect bounds = [view convertRectToBacking:[view bounds]];
return bounds.size.height;
return [view bounds].size.height;
}
CGFloat gio_viewWidth(CFTypeRef viewRef) {
NSView *view = (__bridge NSView *)viewRef;
NSRect bounds = [view convertRectToBacking:[view bounds]];
return bounds.size.width;
return [view bounds].size.width;
}
// Points pr. dp.
@@ -68,8 +67,18 @@ static CGFloat getPointsPerDP(NSScreen *screen) {
// Pixels pr dp.
CGFloat gio_getPixelsPerDP(void) {
NSScreen *screen = [NSScreen mainScreen];
return [screen backingScaleFactor] * getPointsPerDP(screen);
NSScreen *screen = [NSScreen mainScreen];
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) {
@@ -94,11 +103,6 @@ void gio_main(CFTypeRef viewRef, const char *title, CGFloat width, CGFloat heigh
[menuBar addItem:mainMenu];
[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);
NSWindowStyleMask styleMask = NSWindowStyleMaskTitled |
NSWindowStyleMaskResizable |