Skip to content

Commit

Permalink
Merge pull request #815 from troycurtisjr/xinitthreads
Browse files Browse the repository at this point in the history
Call XInitThreads() before any other GUI code initializes.
  • Loading branch information
friday committed Sep 15, 2021
2 parents 6059d50 + 3000409 commit 32b2ab7
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 32 deletions.
18 changes: 1 addition & 17 deletions ulauncher/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from gettext import gettext
from xdg.BaseDirectory import xdg_config_home, xdg_cache_home, xdg_data_dirs, xdg_data_home


DATA_DIR = os.path.join(xdg_data_home, 'ulauncher')
# Use ulauncher_cache dir because of the WebKit bug
# https://bugs.webkit.org/show_bug.cgi?id=151646
Expand Down Expand Up @@ -61,23 +62,6 @@ def get_data_path():
return abs_data_path


def is_wayland():
return os.environ.get('XDG_SESSION_TYPE', '').lower() == 'wayland'


def is_wayland_compatibility_on():
"""
In this mode user won't be able to set app hotkey via preferences
Set hotkey in OS Settings > Devices > Keyboard > Add Hotkey > Command: ulauncher-toggle
GDK_BACKEND is typically unset in Wayland sessions to allow GTK apps to self-select
"""
return is_wayland() and (gdk_backend() == '' or gdk_backend().lower().startswith('wayland'))


def gdk_backend():
return os.environ.get('GDK_BACKEND', '')


@lru_cache()
def get_options():
"""Support for command line options"""
Expand Down
19 changes: 6 additions & 13 deletions ulauncher/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
import logging
import time
from threading import Event
# This xinit import must happen before any GUI libraries are initialized.
# pylint: disable=wrong-import-position,wrong-import-order,ungrouped-imports,unused-import
import ulauncher.utils.xinit # noqa: F401

import gi

# Fixes issue #488
Expand All @@ -16,9 +20,9 @@
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop

from ulauncher.config import (get_version, get_options, is_wayland, is_wayland_compatibility_on,
gdk_backend, CACHE_DIR, CONFIG_DIR, DATA_DIR)
from ulauncher.config import get_version, get_options, CACHE_DIR, CONFIG_DIR, DATA_DIR
from ulauncher.utils.decorator.run_async import run_async
from ulauncher.utils.wayland import is_wayland, is_wayland_compatibility_on
from ulauncher.ui.windows.UlauncherWindow import UlauncherWindow
from ulauncher.ui.AppIndicator import AppIndicator
from ulauncher.utils.Settings import Settings
Expand Down Expand Up @@ -86,17 +90,6 @@ def main():
"""
Main function that starts everything
"""
if is_wayland() and gdk_backend().lower() != 'x11' and not is_wayland_compatibility_on():
warn = """
[!]
Looks like you are in Wayland session
Please run Ulauncher with env var
GDK_BACKEND set to 'x11' like this:
GDK_BACKEND=x11 ulauncher
"""
print(warn, file=sys.stderr)
sys.exit(1)

# start DBus loop
DBusGMainLoop(set_as_default=True)
Expand Down
3 changes: 2 additions & 1 deletion ulauncher/ui/windows/PreferencesUlauncherDialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@
from ulauncher.utils.decorator.glib_idle_add import glib_idle_add
from ulauncher.utils.mypy_extensions import TypedDict
from ulauncher.utils.decorator.run_async import run_async
from ulauncher.utils.wayland import is_wayland
from ulauncher.utils.Settings import Settings
from ulauncher.utils.Router import Router, get_url_params
from ulauncher.utils.AutostartPreference import AutostartPreference
from ulauncher.ui.AppIndicator import AppIndicator
from ulauncher.search.shortcuts.ShortcutsDb import ShortcutsDb
from ulauncher.config import get_data_file, get_options, get_version, is_wayland, EXTENSIONS_DIR
from ulauncher.config import get_data_file, get_options, get_version, EXTENSIONS_DIR


logger = logging.getLogger(__name__)
Expand Down
3 changes: 2 additions & 1 deletion ulauncher/ui/windows/UlauncherWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from ulauncher.ui.ResultItemWidget import ResultItemWidget # noqa: F401
from ulauncher.ui.SmallResultItemWidget import SmallResultItemWidget # noqa: F401

from ulauncher.config import get_data_file, is_wayland_compatibility_on, get_options
from ulauncher.config import get_data_file, get_options
from ulauncher.ui.ItemNavigation import ItemNavigation
from ulauncher.search.Search import Search
from ulauncher.search.apps.AppStatDb import AppStatDb
Expand All @@ -32,6 +32,7 @@
from ulauncher.utils.image_loader import load_image
from ulauncher.utils.version_cmp import gtk_version_is_gte
from ulauncher.utils.desktop.notification import show_notification
from ulauncher.utils.wayland import is_wayland_compatibility_on
from ulauncher.utils.Theme import Theme, load_available_themes
from ulauncher.search.apps.app_watcher import start as start_app_watcher
from ulauncher.search.Query import Query
Expand Down
24 changes: 24 additions & 0 deletions ulauncher/utils/wayland.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""
Module for detecting different states with respect to Wayland.
These functions are in a standalone module to minimize the dependencies so that
ulauncher.utils.xinit can safely use it.
"""
import os


def is_wayland():
return os.environ.get('XDG_SESSION_TYPE', '').lower() == 'wayland'


def is_wayland_compatibility_on():
"""
In this mode user won't be able to set app hotkey via preferences
Set hotkey in OS Settings > Devices > Keyboard > Add Hotkey > Command: ulauncher-toggle
GDK_BACKEND is typically unset in Wayland sessions to allow GTK apps to self-select
"""
return is_wayland() and (gdk_backend() == '' or gdk_backend().lower().startswith('wayland'))


def gdk_backend():
return os.environ.get('GDK_BACKEND', '')
20 changes: 20 additions & 0 deletions ulauncher/utils/xinit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""
Simple module to call XInitThreads() to properly support multi-threaded X11 applications.
"""
from ulauncher.utils.wayland import is_wayland_compatibility_on


if not is_wayland_compatibility_on():
from ctypes import cdll

# Using libX11.so.6 may seem a bit hard-coded, but a quick search on the Internet indicates
# discussion of this ABI version back to before 2009, 12 years prior to when this code was added.
# Also, with most of the development focus on Wayland, the chance of a ABI version bump in X11 is
# exceptionally small. Therefore, no additional fancy discovery methods are necessary.
x11 = cdll.LoadLibrary("libX11.so.6")

# In order to use any X11 calls from multiple threads, the X11 library must be initialized to use
# mutex protection. XInitThreads() sets this up and must be called before any other X11
# initialization is performed. Since this always needs to be called before other imports anyway,
# this module does the init at module import time.
x11.XInitThreads()

0 comments on commit 32b2ab7

Please sign in to comment.