1// LAF OS Library
2// Copyright (C) 2021-2022 Igara Studio S.A.
3// Copyright (C) 2016 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "os/x11/x11.h"
13
14#include "base/debug.h"
15#include "os/x11/event_queue.h"
16#include "os/x11/window.h"
17#include "os/x11/xinput.h"
18
19namespace os {
20
21X11* X11::m_instance = nullptr;
22
23// static
24X11* X11::instance()
25{
26 ASSERT(m_instance);
27 return m_instance;
28}
29
30X11::X11()
31{
32 ASSERT(m_instance == nullptr);
33 m_instance = this;
34
35 // TODO We shouldn't need to call this function (because we
36 // shouldn't be using the m_display from different threads), but
37 // it might be necessary?
38 // https://github.com/aseprite/aseprite/issues/1962
39 XInitThreads();
40
41 m_display = XOpenDisplay(nullptr);
42 m_xim = XOpenIM(m_display, nullptr, nullptr, nullptr);
43}
44
45X11::~X11()
46{
47 ASSERT(m_instance == this);
48
49 // Before closing the X11 display connection, there shouldn't be
50 // more windows opened and the event queue (which store
51 // Event+WindowRef) should be empty. CommonSystem() dtor clears the
52 // queue.
53 ASSERT(WindowX11::countActiveWindows() == 0);
54 ASSERT(((os::EventQueueX11*)os::EventQueue::instance())->isEmpty());
55
56 if (m_xim) {
57 XCloseIM(m_xim);
58 }
59 if (m_display) {
60 if (m_xinput)
61 m_xinput->unload(m_display);
62 XCloseDisplay(m_display);
63 }
64 m_instance = nullptr;
65}
66
67XInput* X11::xinput()
68{
69 if (!m_xinput) {
70 m_xinput = std::make_unique<XInput>();
71 m_xinput->load(m_display);
72 }
73 return m_xinput.get();
74}
75
76void x11_set_user_defined_string_to_detect_stylus(const std::string& str)
77{
78 if (auto x11 = X11::instance())
79 x11->setUserDefinedTablet(str);
80}
81
82} // namespace os
83