Metadata-Version: 2.4
Name: pytray32
Version: 0.1.1
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
event callbacks, compatible with Pillow, NumPy, cv2 without depending on any of them.

Works on Widnows7, 8, 8.1, 10, 11 seamlessly

## 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 of the pointer).
- `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).
