Skip to content

Commit edb1f4c

Browse files
did too many things to count
1 parent 0015c1a commit edb1f4c

File tree

12 files changed

+339
-100
lines changed

12 files changed

+339
-100
lines changed
Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,37 @@
11
#!/usr/bin/python3
22
# -*- coding: utf-8 -*-
33

4+
"""
5+
This module initializes DSI
6+
"""
7+
8+
# built-in modules
49
from platform import system as __system
510

6-
__version__ = "0.0.dev7"
11+
# local modules
12+
from .exceptions import (
13+
DisplayServerNotSupportedError as __DisplayServerNotSupportedError,
14+
OSNotSupportedError as __OSNotSupportedError
15+
)
16+
17+
__version__ = "0.0.dev8"
718
__author__ = "Commandcracker"
819

920
__os_name = __system().lower()
1021

1122
if __os_name == "linux":
12-
from .linux import DSI
23+
from .util import detect_linux_display_server as __detect_linux_display_server
24+
from .util import LinuxDisplayServer as __LinuxDisplayServer
25+
__linux_display_server = __detect_linux_display_server()
26+
27+
if __linux_display_server is __LinuxDisplayServer.X11:
28+
from .linux import DSI
29+
elif __linux_display_server is __LinuxDisplayServer.WAYLAND:
30+
raise NotImplementedError("Wayland is not yet implemented.")
31+
else:
32+
raise __DisplayServerNotSupportedError(
33+
"Your display server is not supported."
34+
)
1335

1436
elif __os_name == "windows":
1537
from .windows import DSI
@@ -18,6 +40,6 @@
1840
raise NotImplementedError("MacOS is not yet implemented.")
1941

2042
else:
21-
raise Exception("Your OS is not supported.")
43+
raise __OSNotSupportedError("Your OS is not supported.")
2244

2345
__all__ = ["DSI"]

display_server_interactions/__main__.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
#!/usr/bin/python3
22
# -*- coding: utf-8 -*-
33

4+
"""
5+
This is an example of DSI
6+
"""
7+
8+
# local modules
49
from . import DSI
510

611

712
def main() -> None:
13+
"""
14+
This is an example of DSI
15+
"""
816
with DSI() as dsi:
917
window = dsi.get_active_window()
1018

1119
print("Active window: ")
12-
print("\tName: {}".format(window.name))
13-
print("\tPID: {}".format(window.pid))
20+
print(f"\tName: {window.name}")
21+
print(f"\tPID: {window.pid}")
1422
if window.xid:
15-
print("\tXID: {}".format(window.xid))
16-
print("\tGeometry: {}".format(window.geometry))
23+
print(f"\tXID: {window.xid}")
24+
print(f"\tGeometry: {window.geometry}")
1725

1826

1927
if __name__ == "__main__":

display_server_interactions/base.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
11
#!/usr/bin/python3
22
# -*- coding: utf-8 -*-
33

4+
"""
5+
This module holds the main DSI class
6+
"""
7+
8+
9+
# built-in modules
410
from abc import ABCMeta, abstractmethod
5-
from .window import WindowBase
611
from platform import system
712

13+
# local modules
14+
from .window import WindowBase
815

9-
class DSIBase(object, metaclass=ABCMeta):
16+
17+
class DSIBase(metaclass=ABCMeta):
18+
"""
19+
Main DSI class
20+
"""
1021
@abstractmethod
1122
def get_active_window(self) -> WindowBase:
1223
"""
1324
Gets the active window.
1425
Returns None if no window is active.
1526
"""
16-
pass
1727

1828
@abstractmethod
1929
def get_all_windows(self) -> list[WindowBase]:
2030
"""
2131
Returns a list of all Windows.
2232
"""
23-
pass
2433

2534
def get_window_by_pid(self, pid: int) -> WindowBase:
2635
"""
@@ -32,6 +41,7 @@ def get_window_by_pid(self, pid: int) -> WindowBase:
3241
for window in all_window:
3342
if window.pid == pid:
3443
return window
44+
return None
3545

3646
def get_window_by_name(self, name: str) -> WindowBase:
3747
"""
@@ -43,6 +53,7 @@ def get_window_by_name(self, name: str) -> WindowBase:
4353
for window in all_window:
4454
if window.name is not None and name in window.name:
4555
return window
56+
return None
4657

4758
@property
4859
def platform(self) -> str:

display_server_interactions/box.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,62 @@
11
#!/usr/bin/python3
22
# -*- coding: utf-8 -*-
33

4+
"""
5+
This module provides a Box class that represents a rectangle with a position and size.
6+
"""
7+
8+
49
class Box(tuple):
10+
"""
11+
A Box represents a rectangle with a position and size.
12+
"""
13+
514
def __init__(self, x: int, y: int, width: int, height: int):
615
"""This is just here for autocompletion"""
7-
pass
816

9-
def __new__(self, x: int, y: int, width: int, height: int):
17+
def __new__(cls, x: int, y: int, width: int, height: int):
1018
return tuple.__new__(Box, (x, y, width, height))
1119

1220
@property
21+
# pylint: disable-next=invalid-name
1322
def x(self) -> int:
23+
"""
24+
Gets the x-coordinate of the box.
25+
"""
1426
return self[0]
1527

1628
@property
29+
# pylint: disable-next=invalid-name
1730
def y(self) -> int:
31+
"""
32+
Gets the y-coordinate of the box.
33+
"""
1834
return self[1]
1935

2036
@property
2137
def width(self) -> int:
38+
"""
39+
Gets the width of the box.
40+
"""
2241
return self[2]
2342

2443
@property
2544
def height(self) -> int:
45+
"""
46+
Gets the height of the box.
47+
"""
2648
return self[3]
2749

2850
def __repr__(self) -> str:
2951
return f'Box(x={self.x}, y={self.y}, width={self.width}, height={self.height})'
3052

3153

3254
def main() -> None:
55+
"""
56+
Creates and displays an example Box object.
57+
"""
3358
try:
59+
# pylint: disable-next=import-outside-toplevel, redefined-builtin
3460
from rich import print
3561
except ImportError:
3662
pass

display_server_interactions/buttons.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
#!/usr/bin/python3
22
# -*- coding: utf-8 -*-
33

4-
class MouseButtons(object):
4+
"""
5+
This module contains everything related too buttons
6+
"""
7+
8+
# pylint: disable=too-few-public-methods
9+
10+
11+
class MouseButtons:
512
"""
613
https://tronche.com/gui/x/xlib/events/keyboard-pointer/keyboard-pointer.html\n
714
/usr/include/X11/X.h: 259-263
@@ -11,3 +18,5 @@ class MouseButtons(object):
1118
MIDDLE = 3
1219
FORWARD = 4
1320
BACKWARD = 5
21+
22+
# pylint: enable=too-few-public-methods
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/python3
2+
# -*- coding: utf-8 -*-
3+
4+
"""Exceptions for DSI."""
5+
6+
7+
class DisplayServerNotSupportedError(Exception):
8+
"""Exception raised when the display server is not supported."""
9+
10+
11+
class OSNotSupportedError(Exception):
12+
"""Exception raised when the operating system is not supported."""

display_server_interactions/image.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
#!/usr/bin/python3
22
# -*- coding: utf-8 -*-
3-
# TODO: add way to get pixel from image
43

5-
class Image(object):
4+
"""
5+
The Image module contains a class to hold the raw data of an image.
6+
"""
7+
8+
from typing import Tuple
9+
10+
11+
class Image:
612
"""
713
A class to that holds the raw data of an image.
814
Use np.array(Image) to get a numpy array of the image.
@@ -14,8 +20,9 @@ def __init__(self, data, width, height):
1420
self.height = height
1521

1622
@property
17-
def __array_interface__(self):
23+
def __array_interface__(self) -> dict:
1824
"""
25+
A property method that returns an interface dictionary for the numpy array interface.
1926
https://docs.scipy.org/doc/numpy/reference/arrays.interface.html
2027
"""
2128
return {
@@ -24,3 +31,16 @@ def __array_interface__(self):
2431
"typestr": "|u1",
2532
"data": self.data,
2633
}
34+
35+
def __repr__(self) -> str:
36+
return f"Image(width={self.width}, height={self.height})"
37+
38+
# pylint: disable-next=invalid-name
39+
def get_pixel(self, x: int, y: int) -> Tuple[int, int, int, int]:
40+
"""
41+
This function retrieves the RGBA values of the pixel located at the specified coordinates,
42+
and returns them as a 4-tuple integer.
43+
"""
44+
pixel_start_index = (y * self.width + x) * 4
45+
pixel_data = self.data[pixel_start_index:pixel_start_index + 4]
46+
return tuple(pixel_data)

display_server_interactions/linux.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
#!/usr/bin/python3
22
# -*- coding: utf-8 -*-
33

4-
# local modules
5-
from .base import DSIBase
6-
from .window import WindowBase
7-
from .image import Image
8-
from .buttons import MouseButtons
9-
from .box import Box
10-
114
# built-in modules
5+
from typing import Optional
126
import logging
137
import ctypes.util
148
from ctypes import (
@@ -29,6 +23,13 @@
2923
_SimpleCData
3024
)
3125

26+
# local modules
27+
from .base import DSIBase
28+
from .window import WindowBase
29+
from .image import Image
30+
from .buttons import MouseButtons
31+
from .box import Box
32+
3233
# Setup Xlib Structures
3334

3435

@@ -202,7 +203,7 @@ def get_logger() -> logging.Logger:
202203
# Setup Xlib Variables
203204

204205

205-
class Masks(object):
206+
class Masks:
206207
"""
207208
https://tronche.com/gui/x/xlib/events/mask.html\n
208209
/usr/include/X11/X.h: 150-175
@@ -235,7 +236,7 @@ class Masks(object):
235236
OwnerGrabButtonMask = 16777216
236237

237238

238-
class EventTypes(object):
239+
class EventTypes:
239240
"""
240241
https://tronche.com/gui/x/xlib/events/types.html\n
241242
/usr/include/X11/X.h: 181-215
@@ -277,7 +278,7 @@ class EventTypes(object):
277278
LASTEvent = 36
278279

279280

280-
class KeyMasks(object):
281+
class KeyMasks:
281282
"""
282283
https://tronche.com/gui/x/xlib/events/keyboard-pointer/keyboard-pointer.html\n
283284
/usr/include/X11/X.h: 221-228
@@ -292,12 +293,12 @@ class KeyMasks(object):
292293
Mod5Mask = 128
293294

294295

295-
class Xlib(object):
296+
class Xlib:
296297
def __init__(self):
297298
# load libX11.so.6
298299
x11 = ctypes.util.find_library("X11")
299300
if not x11:
300-
raise Exception("X11 library not found!")
301+
raise FileNotFoundError("X11 library not found!")
301302
self.xlib = ctypes.cdll.LoadLibrary(x11)
302303

303304
self.xlib.XSetErrorHandler(error_handler)
@@ -370,8 +371,7 @@ def __init__(self):
370371
def __getattribute__(self, __name: str):
371372
if __name in ["xlib", "display", "root_window"]:
372373
return super().__getattribute__(__name)
373-
else:
374-
return self.xlib.__getattribute__(__name)
374+
return self.xlib.__getattribute__(__name)
375375

376376

377377
def get_window_property(xlib: Xlib, window_xid: int, property: str, type: _SimpleCData):
@@ -431,8 +431,7 @@ def name(self) -> str:
431431
)
432432
if name:
433433
return name.decode('utf-8')
434-
else:
435-
return None
434+
return None
436435

437436
@property
438437
def pid(self) -> int:
@@ -453,7 +452,7 @@ def geometry(self) -> Box:
453452
height=gwa.height
454453
)
455454

456-
def get_image(self, geometry: Box = None) -> Image:
455+
def get_image(self, geometry: Optional[Box] = None) -> Image:
457456
if geometry is None:
458457
geometry = self.geometry
459458

@@ -518,7 +517,7 @@ def send_str(self, str: str) -> None:
518517
for chr in str:
519518
self.send_chr(chr)
520519

521-
def warp_pointer(self, x: int, y: int, geometry: Box = None) -> None:
520+
def warp_pointer(self, x: int, y: int, geometry: Optional[Box] = None) -> None:
522521
if geometry is None:
523522
geometry = self.geometry
524523

0 commit comments

Comments
 (0)