RoundTransparentWindow

A PyObjC Example without documentation

Sources

RoundTransparentWindow.py

import sys
from math import floor

import Cocoa
import objc
from objc import super  # noqa: A004
from PyObjCTools import AppHelper


class Controller(Cocoa.NSObject):
    itsWindow = objc.IBOutlet()

    @objc.IBAction
    def changeTransparency_(self, sender):
        """."""
        self.itsWindow.setAlphaValue_(sender.floatValue())
        self.itsWindow.display()


class CustomView(Cocoa.NSView):
    circleImage = objc.ivar()
    pentaImage = objc.ivar()

    def awakeFromNib(self):
        self.circleImage = Cocoa.NSImage.imageNamed_("circle")
        if self.circleImage is None:
            sys.stderr.write("failed to access circle image\n")
            raise RuntimeError
        self.pentaImage = Cocoa.NSImage.imageNamed_("pentagram")
        if self.pentaImage is None:
            sys.stderr.write("failed to access pentagram image\n")
            raise RuntimeError
        self.setNeedsDisplay_(True)

    def drawRect_(self, rect):
        Cocoa.NSColor.clearColor().set()
        Cocoa.NSRectFill(self.frame())
        if self.window().alphaValue() > 0.7:
            self.circleImage.compositeToPoint_operation_(
                Cocoa.NSZeroPoint, Cocoa.NSCompositeSourceOver
            )
        else:
            self.pentaImage.compositeToPoint_operation_(
                Cocoa.NSZeroPoint, Cocoa.NSCompositeSourceOver
            )

        if floor(Cocoa.NSAppKitVersionNumber) <= Cocoa.NSAppKitVersionNumber10_1:
            self.window().setHasShadow_(False)
            self.window().setHasShadow_(True)
        else:
            self.window().invalidateShadow()


class CustomWindow(Cocoa.NSWindow):
    def awakeFromNib(self):
        self.initialLocation = Cocoa.NSPoint()

    def initWithContentRect_styleMask_backing_defer_(
        self, contentRect, aStyle, bufferingType, flag
    ):
        result = super().initWithContentRect_styleMask_backing_defer_(
            contentRect,
            Cocoa.NSBorderlessWindowMask,
            Cocoa.NSBackingStoreBuffered,
            False,
        )
        if result is None:
            sys.stderr.write("superclass call failed\n")
            raise RuntimeError
        result.setBackgroundColor_(Cocoa.NSColor.clearColor())
        result.setLevel_(Cocoa.NSStatusWindowLevel)
        result.setAlphaValue_(1.0)
        result.setOpaque_(False)
        result.setHasShadow_(True)
        return result

    def canBecomeKeyWindow(self):
        return True

    def mouseDragged_(self, theEvent):
        screenFrame = Cocoa.NSScreen.mainScreen().frame()
        if screenFrame is None:
            sys.stderr.write("failed to obtain screen\n")
            raise RuntimeError
        windowFrame = self.frame()
        if windowFrame is None:
            sys.stderr.write("failed to obtain frame\n")
            raise RuntimeError
        currentLocation = self.convertBaseToScreen_(
            self.mouseLocationOutsideOfEventStream()
        )
        newOrigin = Cocoa.NSMakePoint(
            (currentLocation.x - self.initialLocation.x),
            (currentLocation.y - self.initialLocation.y),
        )
        if (newOrigin.y + windowFrame.size.height) > (
            screenFrame.origin.y + screenFrame.size.height
        ):
            newOrigin.y = screenFrame.origin.y + (
                screenFrame.size.height + windowFrame.size.height
            )
        self.setFrameOrigin_(newOrigin)

    def mouseDown_(self, theEvent):
        windowFrame = self.frame()
        if windowFrame is None:
            sys.stderr.write("failed to obtain frame\n")
            raise RuntimeError
        self.initialLocation = self.convertBaseToScreen_(theEvent.locationInWindow())
        self.initialLocation.x -= windowFrame.origin.x
        self.initialLocation.y -= windowFrame.origin.y


if __name__ == "__main__":
    AppHelper.runEventLoop()

setup.py

"""
Script for building the example.

Usage:
    python3 setup.py py2app
"""

from setuptools import setup

setup(
    app=["RoundTransparentWindow.py"],
    data_files=["MainMenu.nib", "circle.tif", "pentagram.tif"],
    setup_requires=["py2app", "pyobjc-framework-Cocoa"],
)