mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-17 17:42:20 +03:00
Appear on task bar in dark mode on Linux
and so enable minimize button. Maybe addresses #440
This commit is contained in:
parent
c5df83eb32
commit
8c2775f6d8
@ -217,7 +217,6 @@ class AppWindow:
|
|||||||
theme_titlebar.bind('<Button-1>', self.drag_start)
|
theme_titlebar.bind('<Button-1>', self.drag_start)
|
||||||
theme_titlebar.bind('<B1-Motion>', self.drag_continue)
|
theme_titlebar.bind('<B1-Motion>', self.drag_continue)
|
||||||
theme_titlebar.bind('<ButtonRelease-1>', self.drag_end)
|
theme_titlebar.bind('<ButtonRelease-1>', self.drag_end)
|
||||||
if platform == 'win32': # Can't work out how to deiconify on Linux
|
|
||||||
theme_minimize = tk.Label(self.theme_menubar, image=self.theme_minimize)
|
theme_minimize = tk.Label(self.theme_menubar, image=self.theme_minimize)
|
||||||
theme_minimize.grid(row=0, column=3, padx=2)
|
theme_minimize.grid(row=0, column=3, padx=2)
|
||||||
theme.button_bind(theme_minimize, self.oniconify, image=self.theme_minimize)
|
theme.button_bind(theme_minimize, self.oniconify, image=self.theme_minimize)
|
||||||
|
105
theme.py
105
theme.py
@ -15,6 +15,8 @@ from ttkHyperlinkLabel import HyperlinkLabel
|
|||||||
|
|
||||||
from config import appname, applongname, config
|
from config import appname, applongname, config
|
||||||
|
|
||||||
|
if __debug__:
|
||||||
|
from traceback import print_exc
|
||||||
|
|
||||||
if platform == 'win32':
|
if platform == 'win32':
|
||||||
import ctypes
|
import ctypes
|
||||||
@ -33,65 +35,66 @@ elif platform == 'linux2':
|
|||||||
Atom = c_ulong
|
Atom = c_ulong
|
||||||
Display = c_void_p # Opaque
|
Display = c_void_p # Opaque
|
||||||
|
|
||||||
# Sending ClientMessage to WM using XSendEvent()
|
PropModeReplace = 0
|
||||||
SubstructureNotifyMask = 1<<19
|
PropModePrepend = 1
|
||||||
SubstructureRedirectMask = 1<<20
|
PropModeAppend = 2
|
||||||
ClientMessage = 33
|
|
||||||
|
|
||||||
_NET_WM_STATE_REMOVE = 0
|
# From xprops.h
|
||||||
_NET_WM_STATE_ADD = 1
|
MWM_HINTS_FUNCTIONS = 1 << 0
|
||||||
_NET_WM_STATE_TOGGLE = 2
|
MWM_HINTS_DECORATIONS = 1 << 1
|
||||||
|
MWM_HINTS_INPUT_MODE = 1 << 2
|
||||||
|
MWM_HINTS_STATUS = 1 << 3
|
||||||
|
MWM_FUNC_ALL = 1 << 0
|
||||||
|
MWM_FUNC_RESIZE = 1 << 1
|
||||||
|
MWM_FUNC_MOVE = 1 << 2
|
||||||
|
MWM_FUNC_MINIMIZE = 1 << 3
|
||||||
|
MWM_FUNC_MAXIMIZE = 1 << 4
|
||||||
|
MWM_FUNC_CLOSE = 1 << 5
|
||||||
|
MWM_DECOR_ALL = 1 << 0
|
||||||
|
MWM_DECOR_BORDER = 1 << 1
|
||||||
|
MWM_DECOR_RESIZEH = 1 << 2
|
||||||
|
MWM_DECOR_TITLE = 1 << 3
|
||||||
|
MWM_DECOR_MENU = 1 << 4
|
||||||
|
MWM_DECOR_MINIMIZE = 1 << 5
|
||||||
|
MWM_DECOR_MAXIMIZE = 1 << 6
|
||||||
|
|
||||||
class XClientMessageEvent_data(Union):
|
class MotifWmHints(Structure):
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
('b', c_char * 20),
|
('flags', c_ulong),
|
||||||
('s', c_short * 10),
|
('functions', c_ulong),
|
||||||
('l', c_long * 5),
|
('decorations', c_ulong),
|
||||||
]
|
('input_mode', c_long),
|
||||||
|
('status', c_ulong),
|
||||||
class XClientMessageEvent(Structure):
|
|
||||||
_fields_ = [
|
|
||||||
('type', c_int),
|
|
||||||
('serial', c_ulong),
|
|
||||||
('send_event', c_int),
|
|
||||||
('display', POINTER(Display)),
|
|
||||||
('window', Window),
|
|
||||||
('message_type', Atom),
|
|
||||||
('format', c_int),
|
|
||||||
('data', XClientMessageEvent_data),
|
|
||||||
]
|
|
||||||
|
|
||||||
class XEvent(Union):
|
|
||||||
_fields_ = [
|
|
||||||
('xclient', XClientMessageEvent),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
try:
|
||||||
xlib = cdll.LoadLibrary('libX11.so.6')
|
xlib = cdll.LoadLibrary('libX11.so.6')
|
||||||
|
XInternAtom = xlib.XInternAtom
|
||||||
|
XInternAtom.argtypes = [POINTER(Display), c_char_p, c_int]
|
||||||
|
XInternAtom.restype = Atom
|
||||||
|
XChangeProperty = xlib.XChangeProperty
|
||||||
|
XChangeProperty.argtypes = [POINTER(Display), Window, Atom, Atom, c_int, c_int, POINTER(MotifWmHints), c_int]
|
||||||
|
XChangeProperty.restype = c_int
|
||||||
XFlush = xlib.XFlush
|
XFlush = xlib.XFlush
|
||||||
XFlush.argtypes = [POINTER(Display)]
|
XFlush.argtypes = [POINTER(Display)]
|
||||||
XFlush.restype = c_int
|
XFlush.restype = c_int
|
||||||
XInternAtom = xlib.XInternAtom
|
|
||||||
XInternAtom.restype = Atom
|
|
||||||
XInternAtom.argtypes = [POINTER(Display), c_char_p, c_int]
|
|
||||||
XOpenDisplay = xlib.XOpenDisplay
|
XOpenDisplay = xlib.XOpenDisplay
|
||||||
XOpenDisplay.argtypes = [c_char_p]
|
XOpenDisplay.argtypes = [c_char_p]
|
||||||
XOpenDisplay.restype = POINTER(Display)
|
XOpenDisplay.restype = POINTER(Display)
|
||||||
XQueryTree = xlib.XQueryTree
|
XQueryTree = xlib.XQueryTree
|
||||||
XQueryTree.argtypes = [POINTER(Display), Window, POINTER(Window), POINTER(Window), POINTER(Window), POINTER(c_uint)]
|
XQueryTree.argtypes = [POINTER(Display), Window, POINTER(Window), POINTER(Window), POINTER(Window), POINTER(c_uint)]
|
||||||
XQueryTree.restype = c_int
|
XQueryTree.restype = c_int
|
||||||
XSendEvent = xlib.XSendEvent
|
|
||||||
XSendEvent.argtypes = [POINTER(Display), Window, c_int, c_long, POINTER(XEvent)]
|
|
||||||
XSendEvent.restype = c_int
|
|
||||||
|
|
||||||
try:
|
|
||||||
dpy = xlib.XOpenDisplay(None)
|
dpy = xlib.XOpenDisplay(None)
|
||||||
XA_ATOM = Atom(4)
|
motif_wm_hints_property = XInternAtom(dpy, b'_MOTIF_WM_HINTS', False)
|
||||||
net_wm_state = XInternAtom(dpy, '_NET_WM_STATE', False)
|
motif_wm_hints_normal = MotifWmHints(MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS,
|
||||||
net_wm_state_above = XInternAtom(dpy, '_NET_WM_STATE_ABOVE', False)
|
MWM_FUNC_RESIZE | MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE | MWM_FUNC_CLOSE,
|
||||||
net_wm_state_sticky = XInternAtom(dpy, '_NET_WM_STATE_STICKY', False)
|
MWM_DECOR_BORDER | MWM_DECOR_RESIZEH | MWM_DECOR_TITLE | MWM_DECOR_MENU | MWM_DECOR_MINIMIZE,
|
||||||
net_wm_state_skip_pager = XInternAtom(dpy, '_NET_WM_STATE_SKIP_PAGER', False)
|
0, 0)
|
||||||
net_wm_state_skip_taskbar = XInternAtom(dpy, '_NET_WM_STATE_SKIP_TASKBAR', False)
|
motif_wm_hints_dark = MotifWmHints(MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS,
|
||||||
|
MWM_FUNC_RESIZE | MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE | MWM_FUNC_CLOSE,
|
||||||
|
0, 0, 0)
|
||||||
except:
|
except:
|
||||||
|
if __debug__: print_exc()
|
||||||
dpy = None
|
dpy = None
|
||||||
|
|
||||||
|
|
||||||
@ -356,25 +359,19 @@ class _Theme:
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
root.withdraw()
|
root.withdraw()
|
||||||
# https://www.tcl-lang.org/man/tcl/TkCmd/wm.htm#M19
|
|
||||||
# https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html#STACKINGORDER
|
|
||||||
root.attributes('-type', theme and 'splash' or 'normal')
|
|
||||||
root.update_idletasks() # Size gets recalculated here
|
root.update_idletasks() # Size gets recalculated here
|
||||||
root.deiconify()
|
if dpy:
|
||||||
root.wait_visibility() # need main window to be displayed before returning
|
|
||||||
if dpy and theme:
|
|
||||||
# Try to display in the taskbar
|
|
||||||
xroot = Window()
|
xroot = Window()
|
||||||
parent = Window()
|
parent = Window()
|
||||||
children = Window()
|
children = Window()
|
||||||
nchildren = c_uint()
|
nchildren = c_uint()
|
||||||
XQueryTree(dpy, root.winfo_id(), byref(xroot), byref(parent), byref(children), byref(nchildren))
|
XQueryTree(dpy, root.winfo_id(), byref(xroot), byref(parent), byref(children), byref(nchildren))
|
||||||
# https://specifications.freedesktop.org/wm-spec/wm-spec-latest.html#idm140200472615568
|
XChangeProperty(dpy, parent, motif_wm_hints_property, motif_wm_hints_property, 32, PropModeReplace, theme and motif_wm_hints_dark or motif_wm_hints_normal, 5)
|
||||||
xevent = XEvent(xclient = XClientMessageEvent(ClientMessage, 0, 0, None, parent, net_wm_state, 32, XClientMessageEvent_data(l = (_NET_WM_STATE_REMOVE, net_wm_state_skip_pager, net_wm_state_skip_taskbar, 1, 0))))
|
|
||||||
XSendEvent(dpy, xroot, False, SubstructureRedirectMask | SubstructureNotifyMask, byref(xevent))
|
|
||||||
xevent = XEvent(xclient = XClientMessageEvent(ClientMessage, 0, 0, None, parent, net_wm_state, 32, XClientMessageEvent_data(l = (_NET_WM_STATE_REMOVE, net_wm_state_sticky, 0, 1, 0))))
|
|
||||||
XSendEvent(dpy, xroot, False, SubstructureRedirectMask | SubstructureNotifyMask, byref(xevent))
|
|
||||||
XFlush(dpy)
|
XFlush(dpy)
|
||||||
|
else:
|
||||||
|
root.overrideredirect(theme and 1 or 0)
|
||||||
|
root.deiconify()
|
||||||
|
root.wait_visibility() # need main window to be displayed before returning
|
||||||
|
|
||||||
if not self.minwidth:
|
if not self.minwidth:
|
||||||
self.minwidth = root.winfo_width() # Minimum width = width on first creation
|
self.minwidth = root.winfo_width() # Minimum width = width on first creation
|
||||||
|
Loading…
x
Reference in New Issue
Block a user