import abc
import logging
from . import ev as ev, wrappers as wrappers, xlib as xlib
from abc import ABC, abstractmethod
from typing import Any, Callable, Dict, List, Optional, Tuple, Union

logger: logging.Logger
ignore_logger: bool
MODIFICATORS: Dict[str, int]
IGNORED_MOD_MASKS: Tuple[int, int, int, int]

class RestartException(Exception): ...

class Actions(ABC, metaclass=abc.ABCMeta):
    @abstractmethod
    def focus_next(self, window: Optional[wrappers.Window] = ...) -> None: ...
    @abstractmethod
    def focus_prev(self, window: Optional[wrappers.Window] = ...) -> None: ...
    @abstractmethod
    def restart(self) -> None: ...
    @abstractmethod
    def activate_window_desktop(self, window: wrappers.Window) -> Optional[bool]: ...

class WM:
    focus_history: List[xlib.Window]
    dpy: xlib.Display
    root: xlib.Window
    atom: xlib.AtomCache
    track_kbd_layout: bool
    actions: Actions
    def __init__(self, loop: ev.Loop) -> None: ...
    def init(self) -> None: ...
    def stop(self, is_exit: bool = ...) -> None: ...
    def create_window(self, window_id: int) -> wrappers.Window: ...
    def get_keycode_from_string(self, key: str) -> Optional[int]: ...
    def parse_keydef(self, keydef: str) -> Optional[List[Tuple[int, int]]]: ...
    def on_key(self, keydef: str, window: Optional[wrappers.Window] = ...) -> Callable[[Callable[[], None]], Callable[[], None]]: ...
    def on_create(self, **matchers: Any) -> Callable[[Callable[[], None]], Callable[[], None]]: ...
    def on_manage(self, **matchers: Any) -> Callable[[Callable[[], None]], Callable[[], None]]: ...
    def on_destroy(self, window: Optional[wrappers.Window] = ...) -> Callable[[Callable[[], None]], Callable[[], None]]: ...
    def on_property_change(self, properties: List[str], window: Optional[wrappers.Window] = ...) -> Callable[[Callable[[], None]], Callable[[], None]]: ...
    def on_timer(self, timeout: float, start: bool = ..., first_timeout: Optional[float] = ...) -> Callable[[Callable[[], None]], Callable[[], None]]: ...
    def get_clients(self) -> List[wrappers.Window]: ...
    def get_stacked_clients(self) -> List[wrappers.Window]: ...
    @property
    def current_window(self) -> Optional[wrappers.Window]: ...
    @property
    def current_desktop(self) -> int: ...
    @property
    def wm_name(self) -> Optional[str]: ...
    @property
    def event_window(self) -> wrappers.Window: ...
    @property
    def event(self) -> Union[xlib.XKeyEvent, xlib.XCreateWindowEvent, xlib.XDestroyWindowEvent, xlib.XPropertyEvent]: ...
    def activate_desktop(self, num: int) -> None: ...
    def find_clients(self, clients: List[wrappers.Window], **matchers: Any) -> List[wrappers.Window]: ...
    def find_client(self, clients: List[wrappers.Window], **matchers: Any) -> Optional[wrappers.Window]: ...
    def focus_window(self, window: xlib.Window) -> None: ...
    def focus_and_raise(self, window: wrappers.Window) -> None: ...
    def place_window_above(self, window: xlib.Window) -> None: ...
    def place_window_below(self, window: xlib.Window) -> None: ...
    def minimize_window(self, window: xlib.Window) -> None: ...
    def restore_window(self, window: xlib.Window) -> None: ...
    def set_window_state(self, window: xlib.Window, taskbar: Optional[bool] = ..., pager: Optional[bool] = ..., decorate: Optional[bool] = ..., otaskbar: Optional[bool] = ..., vmax: Optional[bool] = ..., hmax: Optional[bool] = ...) -> None: ...
    def get_window_geometry(self, window: xlib.Window) -> Tuple[int, int, int, int]: ...
    def get_screen_size(self) -> Tuple[int, int]: ...
    def get_workarea(self, desktop: Optional[int] = ...) -> List[int]: ...
    def moveresize_window(self, window: xlib.Window, x: Optional[int] = ..., y: Optional[int] = ..., w: Optional[int] = ..., h: Optional[int] = ...) -> None: ...
    def moveresize_window2(self, window: wrappers.Window, left: int, top: int, right: int, bottom: int) -> None: ...
    def close_window(self, window: Optional[wrappers.Window] = ...) -> None: ...
    def change_window_desktop(self, window: xlib.Window, desktop: int) -> None: ...
    def on_init(self, func: Callable[[], None]) -> Callable[[], None]: ...
    def on_deinit(self, func: Callable[[], None]) -> Callable[[], None]: ...
    def get_screen_saver_info(self) -> Optional[wrappers.XScreenSaverInfo]: ...
    def reset_dpms(self) -> None: ...
    def get_atom_name(self, atom: xlib.Atom) -> str: ...

class ImmediateWM(WM):
    dpy: xlib.Display
    root: xlib.Window
    atom: xlib.AtomCache
    def __init__(self) -> None: ...

def error_handler(_display: xlib.Display, error: xlib.XErrorEvent) -> int: ...
