Thread overview
Drawing Native OSX Windows with D
Nov 28, 2015
Mike McKee
Nov 28, 2015
Guillaume Piolat
Nov 28, 2015
Jacob Carlborg
Nov 29, 2015
Mike McKee
Nov 29, 2015
Mike McKee
Nov 29, 2015
Jacob Carlborg
Nov 29, 2015
Jacob Carlborg
Nov 29, 2015
Jacob Carlborg
November 28, 2015
Does anyone have a demo that shows how I can call the native OSX API to draw a basic window that's minimizable and can be closed?

I was thinking of making an installer for the Mac, you see. So for instance, people would download a very thin .app file and run that. Because it only uses native window APIs on OSX, it wouldn't be a huge download. That way, this installer can then download the larger payload of my Qt/C++ application that I composed.


November 28, 2015
On Saturday, 28 November 2015 at 10:40:19 UTC, Mike McKee wrote:
> Does anyone have a demo that shows how I can call the native OSX API to draw a basic window that's minimizable and can be closed?
>
> I was thinking of making an installer for the Mac, you see. So for instance, people would download a very thin .app file and run that. Because it only uses native window APIs on OSX, it wouldn't be a huge download. That way, this installer can then download the larger payload of my Qt/C++ application that I composed.

https://github.com/p0nce/DerelictCocoa/tree/master/examples/window
November 28, 2015
On 2015-11-28 11:40, Mike McKee wrote:
> Does anyone have a demo that shows how I can call the native OSX API to
> draw a basic window that's minimizable and can be closed?
>
> I was thinking of making an installer for the Mac, you see. So for
> instance, people would download a very thin .app file and run that.
> Because it only uses native window APIs on OSX, it wouldn't be a huge
> download. That way, this installer can then download the larger payload
> of my Qt/C++ application that I composed.

The recommend ways of distributing applications on OS X, in the preferred order, are:

1. App Store
2. DMG containing an application bundle
3. Native installer
4. Other ways

Building an application that acts like an installer would fall under number 4, that last preferred way.

If you can't/don't want to go with the App Store then why not the second option?

-- 
/Jacob Carlborg
November 29, 2015
On Saturday, 28 November 2015 at 14:05:37 UTC, Jacob Carlborg wrote:
> If you can't/don't want to go with the App Store then why not the second option?

I'm coding an antivirus application for the Mac, using a third-party antivirus engine, in Qt/C++. It needs some things to run under high privileges. As far as I know, you can't do that with a DMG package, but can do it with a PKG package.

I've learned a tremendous amount about PKG packages (the docs are difficult), but the one thing that doesn't seem possible is to download a component from a remote URL with it except via a Perl or Bash script. The PKG flat format supports a way to call a preinstall and postinstall Perl or Bash script. The trouble with that technique, however, is that if you have a 30MB download that takes awhile, the installer screen sits at "Running Package Scripts..." for like 3 minutes (on 2Mbps DSL) and this can confuse the consumer into thinking the installer is hung up, when it isn't.

The thing I'd like to achieve with D is to have my Bash or Perl script call a command line D application that finds the current installer window x,y, hides the Cocoa-based window, draws my new Cocoa-based window to replace it at the same x,y,w,h as the other one, and then runs curl command to download the file, then uses the D application again to stop showing my custom window, unhide the installer window, and exit the Bash script.

So, some things I need to learn in D:

* How to enumerate the currently visible Cocoa windows and their titles or internal names, along with their window handle.

* How to get the x,y of an existing Cocoa window by its window handle.

* How to hide a Cocoa window by its window handle.

* How to draw my own Cocoa window at an x,y coordinate.

* How to destroy my Cocoa window by its window handle.

* How to unhide a previously hidden Cocoa window by its window handle.

If I could pull this off -- I'd make a really nice OSX installer because I could have a small pkg file that downloads and runs, and then its window gets hidden and shows a more-user friendly window (drawn in D and Cocoa) to let the consumer know it's downloading a larger file, and then show the conclusion when done. Currently nothing like that exists on OSX, but does exist on Windows via the Inno Setup and InstallShield platforms.

November 29, 2015
A few interesting things here. I tried to do these things via the new Apple language, Swift.

* You can enum windows, but unlike Microsoft Windows, you have no permissions to hide a window. BTW, hiding a window is a window object method called orderOut(nil), and they only permit it on your own windows, not another application's windows. However, that said, there's a neat AppleScript technique that seems to work in hiding the entire application, rather than just the window.

osascript -e "tell application "System Events" to set visible of process "Installer" to false'

* You can enum Cocoa windows and get x,y,w,h, process ID, window name, and window number (I guess that's an ID) on each. Here's the technique in Swift:

    import Foundation;
    import Cocoa;

    let windows = CGWindowListCopyWindowInfo(
        CGWindowListOption.OptionOnScreenOnly,
        CGWindowID(0))! as NSArray;
    for var i = 0; i < windows.count; i++  {
        let window = windows[i];
        let owner = window["kCGWindowOwnerName"] as! String;
        if owner != "Installer" {
            continue;
        }
       // do something with your window object here
    }

I don't know how to do this in D, but came up with a workaround. My pkg installer will run a Bash script which will hide the Installer window via osascript, show a window that I drew with Swift that basically tells people to wait because it's downloading components, runs curl to download the payload from the server and copy it into the appropriate places (as well as set up system library stuff as needed), and then hide my custom Swift window (the progress window), and then uses osascript again to unhide the installer application.
November 29, 2015
On 2015-11-29 03:30, Mike McKee wrote:

> I'm coding an antivirus application for the Mac, using a third-party
> antivirus engine, in Qt/C++. It needs some things to run under high
> privileges. As far as I know, you can't do that with a DMG package, but
> can do it with a PKG package.

You can do that from inside your application. For example, Xcode has a separate preference pane to download the iOS simulator of various versions, same thing for the documentation.

TextMate and GitX has a menu that allow you to install the command line tools for the application.

> I've learned a tremendous amount about PKG packages (the docs are
> difficult), but the one thing that doesn't seem possible is to download
> a component from a remote URL with it except via a Perl or Bash script.
> The PKG flat format supports a way to call a preinstall and postinstall
> Perl or Bash script. The trouble with that technique, however, is that
> if you have a 30MB download that takes awhile, the installer screen sits
> at "Running Package Scripts..." for like 3 minutes (on 2Mbps DSL) and
> this can confuse the consumer into thinking the installer is hung up,
> when it isn't.

Why can't you bundle everything in the PKG package? What's the advantage of first downloading a small binary/package which then downloads the real application?

> The thing I'd like to achieve with D is to have my Bash or Perl script
> call a command line D application that finds the current installer
> window x,y, hides the Cocoa-based window, draws my new Cocoa-based
> window to replace it at the same x,y,w,h as the other one, and then runs
> curl command to download the file, then uses the D application again to
> stop showing my custom window, unhide the installer window, and exit the
> Bash script.

If you really go that route (still don't see why this would be necessary) I guess DerelictCocoa is the way to go [1], or even better use the new Objective-C support that D got in the latest version of DMD [2].

> So, some things I need to learn in D:
>
> * How to enumerate the currently visible Cocoa windows and their titles
> or internal names, along with their window handle.
>
> * How to get the x,y of an existing Cocoa window by its window handle.
>
> * How to hide a Cocoa window by its window handle.
>
> * How to draw my own Cocoa window at an x,y coordinate.
>
> * How to destroy my Cocoa window by its window handle.
>
> * How to unhide a previously hidden Cocoa window by its window handle.

These are not specific for D. You can search for how to do this in Objective-C/Swift and then figure out how to translate the code to D.

[1] https://github.com/p0nce/DerelictCocoa/tree/master/examples/window
[2] http://dlang.org/spec/objc_interface.html

-- 
/Jacob Carlborg
November 29, 2015
On 2015-11-29 09:03, Mike McKee wrote:
> A few interesting things here. I tried to do these things via the new
> Apple language, Swift.
>
> * You can enum windows, but unlike Microsoft Windows, you have no
> permissions to hide a window. BTW, hiding a window is a window object
> method called orderOut(nil), and they only permit it on your own
> windows, not another application's windows. However, that said, there's
> a neat AppleScript technique that seems to work in hiding the entire
> application, rather than just the window.

There are applications like Moom [1] that lets you control the size and position of the windows of other applications, not sure about hiding windows though. I'm not entirely sure how they work but they require accessibility to be enabled (System Preferences -> Security & Privacy -> Privacy -> Accessibility).

[1] https://manytricks.com/moom/

-- 
/Jacob Carlborg
November 29, 2015
On 2015-11-29 03:30, Mike McKee wrote:

> Currently nothing like that exists on
> OSX, but does exist on Windows via the Inno Setup and InstallShield
> platforms.

I would like to add that if you want to distribute an application on OS X you should do that according to the standards of the platform, which the users are familiar with. Not how it's done on some other platform.

You could also look in to this application [1] that allows you to create PKG packages.

[1] http://s.sudre.free.fr/Software/Packages/about.html

-- 
/Jacob Carlborg