5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 13:02:04 +08:00

[v2] Introduce size and physical size of screens (#2856)

This commit is contained in:
stffabi 2023-08-26 02:11:01 +02:00 committed by GitHub
parent 427fe7e8d3
commit 761efed84d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 92 additions and 10 deletions

View File

@ -18,6 +18,8 @@ typedef struct Screen {
int isPrimary; int isPrimary;
int height; int height;
int width; int width;
int pHeight;
int pWidth;
} Screen; } Screen;
@ -48,14 +50,42 @@ Screen GetNthScreen(int nth, void *inctx){
returnScreen.isPrimary = nth==0; returnScreen.isPrimary = nth==0;
returnScreen.height = (int) nthScreen.frame.size.height; returnScreen.height = (int) nthScreen.frame.size.height;
returnScreen.width = (int) nthScreen.frame.size.width; returnScreen.width = (int) nthScreen.frame.size.width;
returnScreen.pWidth = 0;
returnScreen.pHeight = 0;
// https://stackoverflow.com/questions/13859109/how-to-programmatically-determine-native-pixel-resolution-of-retina-macbook-pro
CGDirectDisplayID sid = ((NSNumber *)[nthScreen.deviceDescription
objectForKey:@"NSScreenNumber"]).unsignedIntegerValue;
CFArrayRef ms = CGDisplayCopyAllDisplayModes(sid, NULL);
CFIndex n = CFArrayGetCount(ms);
for (int i = 0; i < n; i++) {
CGDisplayModeRef m = (CGDisplayModeRef) CFArrayGetValueAtIndex(ms, i);
if (CGDisplayModeGetIOFlags(m) & kDisplayModeNativeFlag) {
// This corresponds with "System Settings" -> General -> About -> Displays
returnScreen.pWidth = CGDisplayModeGetPixelWidth(m);
returnScreen.pHeight = CGDisplayModeGetPixelHeight(m);
break;
}
}
CFRelease(ms);
if (returnScreen.pWidth == 0 || returnScreen.pHeight == 0) {
// If there was no native resolution take a best fit approach and use the backing pixel size.
NSRect pSize = [nthScreen convertRectToBacking:nthScreen.frame];
returnScreen.pHeight = (int) pSize.size.height;
returnScreen.pWidth = (int) pSize.size.width;
}
return returnScreen; return returnScreen;
} }
*/ */
import "C" import "C"
import ( import (
"github.com/wailsapp/wails/v2/internal/frontend"
"unsafe" "unsafe"
"github.com/wailsapp/wails/v2/internal/frontend"
) )
func GetAllScreens(wailsContext unsafe.Pointer) ([]frontend.Screen, error) { func GetAllScreens(wailsContext unsafe.Pointer) ([]frontend.Screen, error) {
@ -65,11 +95,21 @@ func GetAllScreens(wailsContext unsafe.Pointer) ([]frontend.Screen, error) {
for screeNum := 0; screeNum < numScreens; screeNum++ { for screeNum := 0; screeNum < numScreens; screeNum++ {
screenNumC := C.int(screeNum) screenNumC := C.int(screeNum)
cScreen := C.GetNthScreen(screenNumC, wailsContext) cScreen := C.GetNthScreen(screenNumC, wailsContext)
screen := frontend.Screen{ screen := frontend.Screen{
Height: int(cScreen.height), Height: int(cScreen.height),
Width: int(cScreen.width), Width: int(cScreen.width),
IsCurrent: cScreen.isCurrent == C.int(1), IsCurrent: cScreen.isCurrent == C.int(1),
IsPrimary: cScreen.isPrimary == C.int(1), IsPrimary: cScreen.isPrimary == C.int(1),
Size: frontend.ScreenSize{
Height: int(cScreen.height),
Width: int(cScreen.width),
},
PhysicalSize: frontend.ScreenSize{
Height: int(cScreen.pHeight),
Width: int(cScreen.pWidth),
},
} }
screens = append(screens, screen) screens = append(screens, screen)
} }

View File

@ -16,6 +16,7 @@ typedef struct Screen {
int isPrimary; int isPrimary;
int height; int height;
int width; int width;
int scale;
} Screen; } Screen;
int GetNMonitors(GtkWindow *window){ int GetNMonitors(GtkWindow *window){
@ -36,14 +37,16 @@ Screen GetNThMonitor(int monitor_num, GtkWindow *window){
screen.isPrimary = gdk_monitor_is_primary(monitor); screen.isPrimary = gdk_monitor_is_primary(monitor);
screen.height = geometry.height; screen.height = geometry.height;
screen.width = geometry.width; screen.width = geometry.width;
screen.scale = gdk_monitor_get_scale_factor(monitor);
return screen; return screen;
} }
*/ */
import "C" import "C"
import ( import (
"sync"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/wailsapp/wails/v2/internal/frontend" "github.com/wailsapp/wails/v2/internal/frontend"
"sync"
) )
type Screen = frontend.Screen type Screen = frontend.Screen
@ -59,11 +62,21 @@ func GetAllScreens(window *C.GtkWindow) ([]Screen, error) {
numMonitors := C.GetNMonitors(window) numMonitors := C.GetNMonitors(window)
for i := 0; i < int(numMonitors); i++ { for i := 0; i < int(numMonitors); i++ {
cMonitor := C.GetNThMonitor(C.int(i), window) cMonitor := C.GetNThMonitor(C.int(i), window)
screen := Screen{ screen := Screen{
IsCurrent: cMonitor.isCurrent == 1, IsCurrent: cMonitor.isCurrent == 1,
IsPrimary: cMonitor.isPrimary == 1, IsPrimary: cMonitor.isPrimary == 1,
Width: int(cMonitor.width), Width: int(cMonitor.width),
Height: int(cMonitor.height), Height: int(cMonitor.height),
Size: frontend.ScreenSize{
Width: int(cMonitor.width),
Height: int(cMonitor.height),
},
PhysicalSize: frontend.ScreenSize{
Width: int(cMonitor.width * cMonitor.scale),
Height: int(cMonitor.height * cMonitor.scale),
},
} }
screens = append(screens, screen) screens = append(screens, screen)
} }

View File

@ -5,10 +5,12 @@ package windows
import ( import (
"fmt" "fmt"
"github.com/pkg/errors"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
"syscall" "syscall"
"unsafe" "unsafe"
"github.com/pkg/errors"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
) )
func MonitorsEqual(first w32.MONITORINFO, second w32.MONITORINFO) bool { func MonitorsEqual(first w32.MONITORINFO, second w32.MONITORINFO) bool {
@ -66,13 +68,26 @@ func EnumProc(hMonitor w32.HMONITOR, hdcMonitor w32.HDC, lprcMonitor *w32.RECT,
return w32.TRUE return w32.TRUE
} }
height := lprcMonitor.Right - lprcMonitor.Left width := lprcMonitor.Right - lprcMonitor.Left
width := lprcMonitor.Bottom - lprcMonitor.Top height := lprcMonitor.Bottom - lprcMonitor.Top
ourMonitorData.IsPrimary = monInfo.DwFlags&w32.MONITORINFOF_PRIMARY == 1 ourMonitorData.IsPrimary = monInfo.DwFlags&w32.MONITORINFOF_PRIMARY == 1
ourMonitorData.Height = int(width) ourMonitorData.Height = int(height)
ourMonitorData.Width = int(height) ourMonitorData.Width = int(width)
ourMonitorData.IsCurrent = MonitorsEqual(*currentMonInfo, *monInfo) ourMonitorData.IsCurrent = MonitorsEqual(*currentMonInfo, *monInfo)
ourMonitorData.PhysicalSize.Width = int(width)
ourMonitorData.PhysicalSize.Height = int(height)
var dpiX, dpiY uint
w32.GetDPIForMonitor(hMonitor, w32.MDT_EFFECTIVE_DPI, &dpiX, &dpiY)
if dpiX == 0 || dpiY == 0 {
screenContainer.errors = append(screenContainer.errors, fmt.Errorf("unable to get DPI for screen"))
screenContainer.monitors = append(screenContainer.monitors, Screen{})
return w32.TRUE
}
ourMonitorData.Size.Width = winc.ScaleToDefaultDPI(ourMonitorData.PhysicalSize.Width, dpiX)
ourMonitorData.Size.Height = winc.ScaleToDefaultDPI(ourMonitorData.PhysicalSize.Height, dpiY)
// the reason we need a container is that we have don't know how many times this function will be called // the reason we need a container is that we have don't know how many times this function will be called
// this "append" call could potentially do an allocation and rewrite the pointer to monitors. So we save the pointer in screenContainer.monitors // this "append" call could potentially do an allocation and rewrite the pointer to monitors. So we save the pointer in screenContainer.monitors
// and retrieve the values after all EnumProc calls // and retrieve the values after all EnumProc calls

View File

@ -48,8 +48,21 @@ const (
type Screen struct { type Screen struct {
IsCurrent bool `json:"isCurrent"` IsCurrent bool `json:"isCurrent"`
IsPrimary bool `json:"isPrimary"` IsPrimary bool `json:"isPrimary"`
Width int `json:"width"`
Height int `json:"height"` // Deprecated: Please use Size and PhysicalSize
Width int `json:"width"`
// Deprecated: Please use Size and PhysicalSize
Height int `json:"height"`
// Size is the size of the screen in logical pixel space, used when setting sizes in Wails
Size ScreenSize `json:"size"`
// PhysicalSize is the physical size of the screen in pixels
PhysicalSize ScreenSize `json:"physicalSize"`
}
type ScreenSize struct {
Width int `json:"width"`
Height int `json:"height"`
} }
// MessageDialogOptions contains the options for the Message dialogs, EG Info, Warning, etc runtime methods // MessageDialogOptions contains the options for the Message dialogs, EG Info, Warning, etc runtime methods

View File

@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added sveltekit.mdx guide. Added by @figuerom16 in [PR](https://github.com/wailsapp/wails/pull/2771) - Added sveltekit.mdx guide. Added by @figuerom16 in [PR](https://github.com/wailsapp/wails/pull/2771)
- Added ProgramName option to [linux.Options](/docs/reference/options#linux). Added by @lyimmi in [PR](https://github.com/wailsapp/wails/pull/2817) - Added ProgramName option to [linux.Options](/docs/reference/options#linux). Added by @lyimmi in [PR](https://github.com/wailsapp/wails/pull/2817)
- Added new community tempalte wails-sveltekit-ts. Added by [@haukened](https://github.com/haukened) in [PR](https://github.com/wailsapp/wails/pull/2851) - Added new community tempalte wails-sveltekit-ts. Added by [@haukened](https://github.com/haukened) in [PR](https://github.com/wailsapp/wails/pull/2851)
- Added support for retrieving the logical and physical screen size in the screen api. Added by @stffabi in [PR](https://github.com/wailsapp/wails/pull/2856)
### Changed ### Changed