Metadata-Version: 2.4
Name: pytray32
Version: 0.1.0
Summary: Tiny, zero-dependency Windows system-tray icon library for Python, implemented in C99.
Author: pytray32 contributors
License: MIT
Project-URL: Homepage, https://github.com/anomalyco/pytray32
Project-URL: Source, https://github.com/anomalyco/pytray32
Project-URL: Bug Tracker, https://github.com/anomalyco/pytray32/issues
Keywords: windows,tray,trayicon,notifyicon,systray,shell,win32
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: Microsoft :: Windows :: Windows 7
Classifier: Operating System :: Microsoft :: Windows :: Windows 8
Classifier: Operating System :: Microsoft :: Windows :: Windows 10
Classifier: Operating System :: Microsoft :: Windows :: Windows 11
Classifier: Programming Language :: C
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Desktop Environment
Classifier: Topic :: System :: Shells
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: pillow
Requires-Dist: Pillow>=8.0; extra == "pillow"
Dynamic: license-file

# pytray32

A tiny, **zero-dependency** Windows system-tray icon library for Python, written
in conservative C99 (Win32 API only). It exposes a small, .NET `NotifyIcon`-like
API with tray icons, tooltip, balloon notifications, context menus, and mouse
event callbacks — no Pillow, NumPy, or external DLLs required.

## Features

- Tray icon with tooltip and **balloon notifications**
- Context menus (dynamic, thread-safe) with submenus and separators
- Icon loading from `.ico` files, raw ICO bytes, or (optionally) a `PIL.Image`
- Event callbacks: `click`, `doubleClick`, `mouseClick`, `mouseDown`, `mouseUp`,
  `mouseMove` (opt-in), and balloon `shown`/`clicked`/`closed`
- A dedicated message-loop thread for responsiveness
- Native Win32 only; small compiled size; MIT licensed

## Requirements

- Python **3.8+** on **Windows 7 / 8 / 10 / 11** (32-bit and 64-bit)
- No mandatory runtime dependencies
- [Pillow](https://pypi.org/project/Pillow/) is **optional** — only needed if
  you want to load icons from `PIL.Image` objects (`pip install pytray32[pillow]`)

## Install

```bash
pip install pytray32
```

## Quick example

```python
import pytray32
from pytray32 import NotifyIcon, Menu, MenuItem


def on_click(evt):
    print("clicked at (%d, %d)" % (evt.x, evt.y))


def on_exit(item):
    icon.close()


def main():
    menu = Menu(
        MenuItem("Hello", lambda item: print("Hello!")),
        MenuItem("Exit", on_exit),
    )

    icon = NotifyIcon(menu=menu)
    icon.setTooltip("pytray32 demo")
    icon.onClick(on_click)
    icon.show()
    icon.notify("pytray32", "Running in the tray", iconFlag="info")

    import time
    try:
        while icon.visible:
            time.sleep(0.25)
    except KeyboardInterrupt:
        pass
    finally:
        icon.close()


if __name__ == "__main__":
    main()
```

A right-click on the tray icon opens the menu; left-click fires `on_click`,
and the balloon tip demonstrates `notify(...)`. Cleanup is explicit via
`icon.close()` (no `atexit` registration). See `examples/` for more.

## Build from source

The package compiles a small C extension (`pytray32._native`). You need either
**MinGW-w64 (GCC)** or **MSVC (Visual Studio Build Tools)** on Windows.

### MinGW-w64 (recommended for local dev)

```bash
python setup.py build_ext --inplace -c mingw32
```

This produces `src/pytray32/_native.pyd`. To run an example without installing
the package, point `PYTHONPATH` at the `src/` directory:

```powershell
$env:PYTHONPATH="$PWD/src"; python.exe .\examples\balloon_example.py
```

### MSVC (used by the CI / Visual Studio)

```bash
python setup.py build_ext --inplace -c msvc
```

### Editable install (developers)

```bash
pip install -e . --no-build-isolation
```

The compiled extension lives at `src/pytray32/_native.pyd`. Rebuild after any
change to the `.c` files.

## API reference

### Module functions

- `init()` / `shutdown()` — start/stop the shared tray message-loop thread.
  Normally called automatically by `NotifyIcon`; exposed for advanced use.

### `NotifyIcon(icon=None, menu=None, tooltip=None, highDpi=True)`

Creates and registers a tray icon. `highDpi=True` (default) enables
per-monitor DPI awareness via the Win32 API. The call is best-effort and only
ever *upgrades* awareness (silently ignored if a host GUI framework already set
it).

**Methods**

- `show()` / `hide()` — show or hide the icon.
- `close()` — remove the icon and release resources. Idempotent; also called by
  `__del__`, so no `atexit` registration is needed.
- `setTooltip(text)` — set the hover tooltip.
- `loadIcon(obj)` / `setIcon(obj)` — set the icon from a file path (`str`),
  raw ICO `bytes`, or a `PIL.Image`.
- `setIconFromBuffer(data, width, height, format="RGBA")` — set the icon from a raw
  pixel buffer. `format` is one of `RGBA`, `BGRA`, `RGB`, `BGR`. `data` is any
  contiguous bytes-like object (e.g. `PIL.Image.tobytes()`, a NumPy array's
  `.tobytes()`, or an OpenCV `Mat`/`ndarray`). The C side allocates the BGRA
  buffer, converts, and builds the `HICON`.
- `notify(title, text, iconFlag="none", timeout=5000)` — show a balloon.
  `iconFlag` is `none`/`info`/`warning`/`error`/`user` (or int `0`–`4`).
  `timeout` is milliseconds (honored on legacy systems, ignored by the shell
  on Vista+).

**Event callbacks** (each receives one event object)

- `onClick`, `onDoubleClick`, `onMouseClick`, `onMouseDown`, `onMouseUp`
- `onMouseMove` — only fires when `trackMouse=True`.
- `onBalloonTipShown`, `onBalloonTipClicked`, `onBalloonTipClosed`

**Properties**

- `tooltip` (str), `icon` (ICO `bytes` or `None`), `menu` (`Menu` or `None`),
  `trackMouse` (bool, default `False`), `visible` (bool, read-only),
  `uid` (int, read-only).
- `balloonTitle`, `balloonText`, `balloonIcon` — remembered defaults used when
  the matching `notify()` argument is omitted.

### Events

- `NotifyIconEvent` — `type`, `button` (0 left / 1 right / 2 middle / -1 none),
  `clicks` (1 or 2), `x`, `y` (screen coordinates from `GetMessagePos`).
- `MenuEvent` (passed to menu/item callbacks) — `type`, `button`, `x`, `y`,
  `text` (the item's label).

### `Menu` and `MenuItem`

- `Menu(*items)` — build a menu. Methods: `add(item)`, `insert(index, item)`,
  `remove(item)`, `clear()`, `show()`.
- `MenuItem(text, callback=None, *, enabled=True, checked=False,
  default=False, visible=True, icon=None, submenu=None)` — `callback` receives a
  `MenuEvent`. The `text`, `enabled`, `checked`, `default`, `visible`, and
  `icon` attributes can be mutated live.
- `MenuSeparator()` — a non-selectable divider line.

### Image adapters (optional dependencies)

Imported from the top level for convenience:

```python
from pytray32 import setIconFromPillow, setIconFromNumpy, setIconFromOpenCV

setIconFromPillow(icon, pil_image)   # PIL.Image
setIconFromNumpy(icon, array)        # HxWx3 (RGB) or HxWx4 (RGBA)
setIconFromOpenCV(icon, mat)         # HxWx3 (BGR) or HxWx4 (BGRA)
```

Each lazily imports its library, so pytray32 never requires Pillow, NumPy, or
OpenCV unless you actually use the corresponding adapter. The low-level
`toBuffer(image) -> (width, height, rgba_bytes)` is also available for Pillow.

## License

MIT — see [LICENSE](LICENSE).
