Pacharapol Withayasakpunt Pacharapol Withayasakpunt
Thu, September 10, 2020

Maximize (not fullscreen) your cross-platform desktop application

If not for macOS "fullscreen" (and some Linux), it wouldn't be a pain.

I have realize the solution for a while, with Golang and Lorca. Nonetheless, it uses cgo.

package main

import (
  "fmt"
  "log"

  /*
    #cgo darwin LDFLAGS: -framework CoreGraphics

    #if defined(__APPLE__)
    #include <CoreGraphics/CGDisplayConfiguration.h>
    int display_width() {
    return CGDisplayPixelsWide(CGMainDisplayID());
    }
    int display_height() {
    return CGDisplayPixelsHigh(CGMainDisplayID());
    }
    #else
    int display_width() {
    return 0;
    }
    int display_height() {
    return 0;
    }
    #endif
  */
  "C"

  "github.com/zserge/lorca"
)

func main() {
  if lorca.LocateChrome() == "" {
    lorca.PromptDownload()
    log.Fatal(fmt.Errorf("cannot open outside Chrome desktop application"))
  } else {
    width := int(C.display_width())
    height := int(C.display_height())

    if width == 0 || height == 0 {
      width = 1024
      height = 768
    }

    w, err := lorca.New("https://example.com", "", width, height)
    if err != nil {
      log.Fatal(err)
    }

    defer w.Close()

    // This does nothing in macOS, BTW.
    w.SetBounds(lorca.Bounds{
      WindowState: lorca.WindowStateMaximized,
    })

    <-w.Done()
  }
}

Then, you can cross-compile for all major platforms using xgo.

https://github.com/karalabe/xgo

BRANCH=${<BRANCH_NAME>:-"master"}
REPO=<REPO_NAME>

$(go env GOPATH)/bin/xgo <br />  -ldflags="-H windowsgui" <br />  -branch=BRANCH <br />  -targets=windows/* <br />  REPO

if [[ $(go env GOOS) == 'darwin' ]]; then
  go build "${PWD##*/}.app"
  $(go env GOPATH)/bin/xgo <br />    -branch=BRANCH <br />    -targets=linux/* <br />    REPO
else
  $(go env GOPATH)/bin/xgo <br />    -branch=BRANCH <br />    -targets=linux/*,darwin/amd64 <br />    REPO

  rm *-darwin*.app
  for f in *-darwin*; do mv "$f" "$f.app"; done
fi

The question still remains. What if I don't use Lorca, Chrome DevTools Protocol, or any other frameworks with built-in maximize, so what should I do? (BTW, Electron has built-in maximization, but webview/webview and Neutralino.js don't have one…)

I have an approximate answer in cgo.

import (
  "runtime"

  /*
     #cgo darwin LDFLAGS: -framework CoreGraphics
     #cgo linux pkg-config: x11

     #if defined(__APPLE__)
     #include <CoreGraphics/CGDisplayConfiguration.h>
     int display_width() {
       return CGDisplayPixelsWide(CGMainDisplayID());
     }
     int display_height() {
       return CGDisplayPixelsHigh(CGMainDisplayID());
     }
     #elif defined(_WIN32)
     #include <wtypes.h>
     int display_width() {
       RECT desktop;
       const HWND hDesktop = GetDesktopWindow();
       GetWindowRect(hDesktop, &desktop);
       return desktop.right;
     }
     int display_height() {
       RECT desktop;
       const HWND hDesktop = GetDesktopWindow();
       GetWindowRect(hDesktop, &desktop);
       return desktop.bottom;
     }
     #else
     #include <X11/Xlib.h>
     int display_width() {
       Display* d = XOpenDisplay(NULL);
       Screen*  s = DefaultScreenOfDisplay(d);
       return s->width;
     }
     int display_height() {
       Display* d = XOpenDisplay(NULL);
       Screen*  s = DefaultScreenOfDisplay(d);
       return s->height;
     }
     #endif
  */
  "C"
)

func getFullscreenSize() (int, int) {
  width := int(C.display_width())
  height := int(C.display_height())

  // Current method of getting screen size in linux and windows makes it fall offscreen
  if runtime.GOOS == "linux" || runtime.GOOS == "windows" {
    width = width - 50
    height = height - 100
  }

  if width == 0 || height == 0 {
    width = 1024
    height = 768
  }

  return width, height
}

Not really fullscreen in Windows and Linux. Also, when compiling for Linux, you cannot use xgo -- I use Docker instead.

ARG ARCH=""
FROM ${ARCH}debian
RUN apt-get update
RUN apt-get install -y --no-install-recommends build-essential 
RUN apt-get install -y xorg-dev
RUN apt-get install -y golang git

And,

for arch in amd64 i386
  do
    docker build --build-arg ARCH=$arch/ -t ${PWD##*/}-$arch .
  done

for arch in amd64 i386
  do
    docker run --rm -v <br />      "$PWD":/usr/app <br />      -w /usr/app <br />      ${PWD##*/}-$arch <br />      go build -o "${PWD##*/}-$arch"
  done

BTW, I've just found docker xbuild.

https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/