Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

donotdisturb: switch x11 fullscreen detection to Xlib #655

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 53 additions & 32 deletions safeeyes/plugins/donotdisturb/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Skip Fullscreen plugin skips the break if the active window is fullscreen.
NOTE: Do not remove the unused import 'GdkX11' because it is required in Ubuntu 14.04
"""

import os
Expand All @@ -27,10 +26,9 @@
import subprocess

import gi
gi.require_version('Gdk', '3.0')
from gi.repository import Gdk
from gi.repository import GdkX11 # noqa F401
gi.require_version('Gio', '2.0')
from gi.repository import Gio
import Xlib
from safeeyes import utility

context = None
Expand Down Expand Up @@ -63,36 +61,59 @@ def is_active_window_skipped_xorg(pre_break):
This method must be executed by the main thread. If not, it will cause random failure.
"""
logging.info('Searching for full-screen application')
screen = Gdk.Screen.get_default()

active_window = screen.get_active_window()
x11_display = Xlib.display.Display()
active_window = x11_display.get_input_focus().focus

if active_window:
active_xid = str(active_window.get_xid())
cmdlist = ['xprop', '-root', '-notype', '-id',
active_xid, 'WM_CLASS', '_NET_WM_STATE']

try:
stdout = subprocess.check_output(cmdlist).decode('utf-8')
except subprocess.CalledProcessError:
logging.warning('Error in finding full-screen application')
else:
if stdout:
is_fullscreen = 'FULLSCREEN' in stdout
# Extract the process name
process_names = re.findall('"(.+?)"', stdout)
if process_names:
process_name = process_names[1].lower()
if _window_class_matches(process_name, skip_break_window_classes):
return True
elif _window_class_matches(process_name, take_break_window_classes):
if is_fullscreen and unfullscreen_allowed and not pre_break:
try:
active_window.unfullscreen()
except BaseException as e:
logging.error('Error in unfullscreen the window ' + process_name, exc_info=e)
return False

return is_fullscreen
NET_WM_STATE = x11_display.intern_atom("_NET_WM_STATE")
NET_WM_STATE_FULLSCREEN = x11_display.intern_atom("_NET_WM_STATE_FULLSCREEN")

props = active_window.get_full_property(NET_WM_STATE, Xlib.Xatom.ATOM)
is_fullscreen = props.value and NET_WM_STATE_FULLSCREEN in props.value.tolist()

process_names = active_window.get_wm_class()

if is_fullscreen:
logging.info("fullscreen window found")

if process_names:
process_name = process_names[1].lower()
if _window_class_matches(process_name, skip_break_window_classes):
logging.info("found uninterruptible window")
return True
elif _window_class_matches(process_name, take_break_window_classes):
logging.info("found interruptible window")
if is_fullscreen and unfullscreen_allowed and not pre_break:
logging.info("interrupting interruptible window")
try:
# To change the fullscreen state, we cannot simply set the property - we must send a ClientMessage event
# See https://specifications.freedesktop.org/wm-spec/1.3/ar01s05.html#id-1.6.8
root_window = x11_display.screen().root

cm_event = Xlib.protocol.event.ClientMessage(
window = active_window,
client_type = NET_WM_STATE,
data = (32, [
0, # _NET_WM_STATE_REMOVE
NET_WM_STATE_FULLSCREEN,
0, # other property, must be 0
1, # source indication
0 # must be 0
])
)

mask = Xlib.X.SubstructureRedirectMask | Xlib.X.SubstructureNotifyMask

root_window.send_event(cm_event, event_mask = mask)

x11_display.sync()

except BaseException as e:
logging.error('Error in unfullscreen the window ' + process_name, exc_info=e)
return False

return is_fullscreen

return False

Expand Down
Loading