Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
start/stop the gtk eventloop instead
Browse files Browse the repository at this point in the history
  • Loading branch information
IanButterworth committed Jan 13, 2022
1 parent 9a6d3bd commit 4a07406
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 30 deletions.
3 changes: 2 additions & 1 deletion src/GLib/GLib.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export set_gtk_property!, get_gtk_property
export GConnectFlags
export @sigatom, cfunction_

const IDLE = Ref{Bool}(true)

cfunction_(@nospecialize(f), r, a::Tuple) = cfunction_(f, r, Tuple{a...})

Expand All @@ -42,6 +41,8 @@ cfunction_(@nospecialize(f), r, a::Tuple) = cfunction_(f, r, Tuple{a...})
end
end

const gtk_eventloop_f = Ref{Function}()

# local function, handles Symbol and makes UTF8-strings easier
const AbstractStringLike = Union{AbstractString, Symbol}
bytestring(s) = String(s)
Expand Down
7 changes: 3 additions & 4 deletions src/GLib/signals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,7 @@ function uv_prepare(src::Ptr{Nothing}, timeout::Ptr{Cint})
global expiration, uv_pollfd
local tmout_ms::Cint
evt = Base.eventloop()
if IDLE[]
return Int32(1)
elseif !_isempty_workqueue()
if !_isempty_workqueue()
tmout_ms = 0
elseif !uv_loop_alive(evt)
tmout_ms = -1
Expand Down Expand Up @@ -318,7 +316,7 @@ end
function uv_check(src::Ptr{Nothing})
global expiration
ex = expiration::UInt64
if !_isempty_workqueue() || IDLE[]
if !_isempty_workqueue()
return Int32(1)
elseif !uv_loop_alive(Base.eventloop())
return Int32(0)
Expand Down Expand Up @@ -383,6 +381,7 @@ end
@deprecate g_timeout_add(interval, cb, user_data) g_timeout_add(() -> cb(user_data), interval)

function g_idle_add(cb::Function)
gtk_eventloop_f[](true)
callback = @cfunction(_g_callback, Cint, (Ref{Function},))
ref, deref = gc_ref_closure(cb)
return ccall((:g_idle_add_full , libglib),Cint,
Expand Down
48 changes: 31 additions & 17 deletions src/Gtk.jl
Original file line number Diff line number Diff line change
Expand Up @@ -128,35 +128,49 @@ function __init__()
C_NULL, C_NULL, "Julia Gtk Bindings", C_NULL, C_NULL, error_check)
end

# if g_main_depth > 0, a glib main-loop is already running,
# so we don't need to start a new one
if ccall((:g_main_depth, GLib.libglib), Cint, ()) == 0
global gtk_main_task = schedule(Task(gtk_main))
end
# if g_main_depth > 0, a glib main-loop is already running.
# unfortunately this call does not reliably reflect when the loop stops, or restarts, so
# only use it once
gtk_main_running[] = ccall((:g_main_depth, GLib.libglib), Cint, ()) > 0

# Given GLib provides `g_idle_add` to specify what happens during idle, this allows
# that call to also start the eventloop
GLib.gtk_eventloop_f[] = enable_eventloop

AUTO_IDLE[] = get(ENV, "GTK_AUTO_IDLE", "true") == "true"
idle(AUTO_IDLE[])
auto_idle[] = get(ENV, "GTK_AUTO_IDLE", "true") == "true"

# by default, defer starting the event loop until either `show`, `showall`, or `g_idle_add` is called
enable_eventloop(!auto_idle[], force = true)
end

const AUTO_IDLE = Ref{Bool}(true)
const auto_idle = Ref{Bool}(true) # control default via ENV["GTK_AUTO_IDLE"]
const gtk_main_running = Ref{Bool}(false)

"""
Gtk.idle(b::Bool = true)
Gtk.enable_eventloop(b::Bool = true)
Set whether Gtk's event loop should be idle.
Set whether Gtk's event loop is running.
"""
function idle(b::Bool)
GLib.IDLE[] = b
function enable_eventloop(b::Bool = true; force = false)
if b
if !is_eventloop_running()
global gtk_main_task = schedule(Task(gtk_main))
gtk_main_running[] = true
end
else
if is_eventloop_running()
gtk_quit()
gtk_main_running[] = false
end
end
end

"""
Gtk.isidle()::Bool
Gtk.is_eventloop_running()::Bool
Check whether Gtk's event loop is idle.
Check whether Gtk's event loop is running.
"""
function isidle()
GLib.IDLE[]
end
is_eventloop_running() = gtk_main_running[]

const ser_version = Serialization.ser_version
let cachedir = joinpath(splitdir(@__FILE__)[1], "..", "gen")
Expand Down
12 changes: 6 additions & 6 deletions src/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ screen_size(w::GtkWindowLeaf) = screen_size(Gtk.GAccessor.screen(w))
visible(w::GtkWidget) = Bool(ccall((:gtk_widget_get_visible, libgtk), Cint, (Ptr{GObject},), w))
visible(w::GtkWidget, state::Bool) = @sigatom ccall((:gtk_widget_set_visible, libgtk), Nothing, (Ptr{GObject}, Cint), w, state)

const SHOWN_WIDGETS = WeakKeyDict()
const shown_widgets = WeakKeyDict()
function handle_auto_idle(w::GtkWidget)
if AUTO_IDLE[]
idle(false)
SHOWN_WIDGETS[w] = nothing
if auto_idle[]
enable_eventloop(true)
shown_widgets[w] = nothing
signal_connect(w, :destroy) do w
delete!(SHOWN_WIDGETS, w)
isempty(SHOWN_WIDGETS) && idle(true)
delete!(shown_widgets, w)
isempty(shown_widgets) && enable_eventloop(false)
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions src/windows.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ end

resize!(win::GtkWindow, w::Integer, h::Integer) = ccall((:gtk_window_resize, libgtk), Nothing, (Ptr{GObject}, Int32, Int32), win, w, h)

present(win::GtkWindow) = ccall((:gtk_window_present, libgtk), Nothing, (Ptr{GObject},), win)
present(win::GtkWindow) = (handle_auto_idle(win); ccall((:gtk_window_present, libgtk), Nothing, (Ptr{GObject},), win))

fullscreen(win::GtkWindow) = ccall((:gtk_window_fullscreen, libgtk), Nothing, (Ptr{GObject},), win)
fullscreen(win::GtkWindow) = (handle_auto_idle(win); ccall((:gtk_window_fullscreen, libgtk), Nothing, (Ptr{GObject},), win))
unfullscreen(win::GtkWindow) = ccall((:gtk_window_unfullscreen, libgtk), Nothing, (Ptr{GObject},), win)

maximize(win::GtkWindow) = ccall((:gtk_window_maximize, libgtk), Nothing, (Ptr{GObject},), win)
Expand Down

0 comments on commit 4a07406

Please sign in to comment.