Skip to content

Commit bcb0340

Browse files
committed
Add GLib override documentation
Also reformats all documentation text to conform better to editing with proportional type. This commit contributes to #11.
1 parent 8780690 commit bcb0340

14 files changed

Lines changed: 1172 additions & 1566 deletions

docs/Async.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Gio
2+
3+
Most Gio functionality is supported automatically through GObject-Introspection, but LuaGObject provides a helper called `Gio.Async` which makes it easier to use Gio-style asynchronous I/O.
4+
5+
## Asynchronous IO
6+
7+
Gio's native asynchronous operations are based on a traditional callback scheme. Once an operation has started, it is pushed to the background until it is finished where it will then call the registered callback using the results of a given operation as the parameters to the callback. While this pattern is used widely for most asynchronous programming, it also makes code much more difficult to reason about and does not fit well with Lua's native coroutines. Coroutines allow asynchronous code to take on a synchronous feeling, and avoid polluting one's code hierarchy with callbacks while still retaining the advantages of non-blocking I/O, and LuaGObject provides helpers to bridge this gap.
8+
9+
Gio-style asynchronous functions always come as pairs of two methods: `<name>_async` (sometimes just `<name>` without the suffix, especially in newer libraries) which starts an operation, and `<name>_finish` which is called within a registered callback and allows for the retrieval of an operation's results. When LuaGObject's `Gio` override is loaded, LuaGObject will detect these async pairs—within all namespaces, not just Gio's—and when these paired functions are found, it will synthesize a new function called `async_<name>` for each pair, wrapping the native methods using Lua coroutines to convert convert callbacks into synchronous code. For `async_<name>` functions to work, they must be called within the context `Gio.Async`. One can use `Gio.Async.call` to perform an async call as a synchronous call, and `Gio.Async.start` to start the routine in the background.
10+
11+
### The Gio.Async Class
12+
13+
This helper class is implemented by LuaGObject—it does not originate from Gio. It contains the interface for LuaGObject's asynchronous support. This class is entirely static and it is not possible to instantiate.
14+
15+
### Gio.Async.call and Gio.Async.start
16+
17+
local call_results = Gio.Async.call(user_function[, cancellable[, io_priority])(user_args)
18+
local resume_results = Gio.Async.start(user_function[, cancellable[, io_priority])(user_args)
19+
20+
These methods accept user function to be run as argument and return function which starts execution of the user function in async-enabled context.
21+
22+
These functions accept a user-defined Lua function as their first parameter, in which all `async_<name>` functions will become available.
23+
24+
Any `async_<name>` methods called inside context do not accept `io_priority` and `cancellable` arguments (as their `<name>_async` original counterparts do). Instead, the `cancellable` and `io_priority` parameters passed to the originating `Gio.Async.call/start` are used in all `async_<name>` calls.
25+
26+
### Gio.Async.cancellable and Gio.Async.io_priority
27+
28+
Code running inside async-enabled context can query or the change value of the context-default `cancellable` and `io_priority` attributes by getting or setting them as attributes of the static `Gio.Async` class.
29+
30+
If `cancellable` or `io_priority` arguments are not provided to `Gio.Async.start` or `Gio.Async.call`, they are automatically inherited from the currently running async-enabled coroutine if available, otherwise default values are used (if the originating caller is not running in an async-enabled context).
31+
32+
### Simple asynchronous I/O example
33+
34+
This GTK+ 3 example example reacts to the press of button, reads contents of `/etc/passwd` and dumps it to standard output.
35+
36+
local window = Gtk.Window {
37+
... Gtk.Button { id = "button", label = "Breach" }, ...
38+
}
39+
40+
function window.child.button:on_clicked()
41+
local function dump_file(filename)
42+
local file = Gio.File.new_for_path(filename)
43+
local info = file:async_query_info("standard::size", "NONE
44+
local stream = file:async_read()
45+
local bytes = stream:async_read_bytes(info:get_size())
46+
print(bytes.data)
47+
stream:async_close()
48+
end
49+
Gio.Async.start(dump_file)("/etc/passwd")
50+
end
51+
52+
Note that all reading happens while running on background, as the on_clicked() handler finishes while the async operation is still running in the background, so the main thread will never block no matter how big your '/etc/passwd' file is.
53+
54+
For a more detailed look at asynchronous operations, see `samples/giostream.lua`.

docs/Cairo.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Cairo
2+
3+
Cairo is a library for drawing graphics. It is a core part of many Gtk apps, as Gtk uses Cairo for much of its drawing. Cairo is thus an important part of any Gtk app, but Cairo is also not built on GObject and thus is not introspectable through GObject-Introspection which causes significant problems for any binding based on GObject-Introspection, including LuaGObject. To alleviate this, LuaGObject provides its own bindings to some Cairo features.
4+
5+
## Basic Cairo Bindings
6+
7+
Although the implementation of the Cairo binding is different from other GObject—Introspection-based bindings, the difference is not noticeable when using LuaGObject. Cairo is imported the same way as other libraries:
8+
9+
local LuaGObject = require "LuaGObject"
10+
local cairo = LuaGObject.cairo
11+
12+
As with GObject-based libraries which are implemented in C, Cairo's library is internally organized using an object-oriented style, with structs (e.g.: `cairo_t`, `cairo_surface_t`) acting as objects and functions being as methods which act on the objects. LuaGObject exports these within a namespace named `cairo` (e.g.: `cairo.Context`, `cairo.Surface`). To create a new object instance, Cairo has built-in `_create` methods for its classes, and these are mapped to `cairo.Surface.create` for `cairo_surface_create`, etc. It is also possible to invoke them using the constructor syntax LuaGObject makes available for GObject-based libraries by calling the namespace table directly, making the following lines equivalent:
13+
14+
local cr = cairo.Context.create(surface)
15+
16+
local cr = cairo.Context(surface)
17+
18+
### Version Checking
19+
20+
The fields `cairo.version` and `cairo.version_string` contain the runtime's current cairo library version as returned by the C functions `cairo_version()` and `cairo_version_string()`. The C-side `CAIRO_VERSION_ENCODE()` macro is reimplemented as `cairo.version_encode(major, minor, micro)`, and can be used to compare against the contents of `cairo.version` for version-specific functionality. To run separate code with Cairo 1.12 or later:
21+
22+
if cairo.version >= cairo.version_encode(1, 12, 0) then
23+
-- Cairo 1.12-specific code
24+
else
25+
-- Fallback to older cairo version code
26+
end
27+
28+
### Synthetic Properties
29+
30+
Each Cairo object has many getter and setter methods associated with them. LuaGObject exports them in the form of method calls just as the native C interface does, and it also provides property-like access. It is possible to query and assigned to named properties on a Cairo object as with those based on GObject. Here are two identical ways of setting the line width of a `cairo.Context` instance:
31+
32+
local cr = cairo.Context(surface)
33+
cr:set_line_width(10)
34+
print("line width ", cr:get_line_width())
35+
36+
local cr = cairo.Context(surface)
37+
cr.line_width = 10
38+
print("line width ", cr.line_width)
39+
40+
Generally speaking, any pair of `get_<name>()` and `set_<name>()` functions will be accessible as a property in Cairo through LuaGObject.
41+
42+
### cairo.Surface Hierarchy
43+
44+
Cairo's fundamental rendering object is `cairo.Surface`. It also implements many more specialized surfaces which implement rendering to specific targets (e.g.: `cairo.ImageSurface`, `cairo.PdfSurface`, etc) each providing their own class which is logically inherited from `cairo.Surface`. LuaGObject fully implements this inheritance, so calling `cairo.ImageSurface()` returns instance providing all methods and properties from both `cairo.Surface` and `cairo.ImageSurface`.
45+
46+
Additionally, LuaGObject always tracks the real type of a surface, so that even when a method like `cairo.Context.get_target()` (or its associated property, `cairo.Context.target`) will return a `cairo.Surface` instance which LuaGObject will query to determine which precise surface type is actually returned. The following example demonstrates querying a property `.width` of the `cairo.ImageSurface` class from a property which is supposed to return an instance of the generic `cairo.Surface` class:
47+
48+
-- Assumes `cr` is a cairo.Context instance with an assigned surface
49+
print("width of the surface" cr.target.width)
50+
51+
It is also possible to use LuaGObject's typechecking mechanism to check a
52+
surface's underlying type:
53+
54+
if cairo.ImageSurface:is_type_of(cr.target) then
55+
print("width of the surface" cr.target.width)
56+
else
57+
print("unsupported type of the surface")
58+
end
59+
60+
### cairo.Pattern Hierarchy
61+
62+
Cairo's pattern API hides the inheritance of assorted pattern types. LuaGObject's binding exposes this hierarchy in the same way as it does for surface types, described in the previous section. The pattern hierarchy is as follows:
63+
64+
- cairo.Pattern
65+
- cairo.SolidPattern
66+
- cairo.SurfacePattern
67+
- cairo.GradientPattern
68+
- cairo.LinearPattern
69+
- cairo.RadialPattern
70+
- cairo.MeshPattern
71+
72+
Patterns can be created using static factory methods on `cairo.Pattern` as described in Cairo's documentation, but LuaGObject additionally maps creation methods to subclass constructors as it does with GObject-based libraries. The following snippets are thus equivalent:
73+
74+
local pattern = cairo.Pattern.create_linear(0, 0, 10, 10)
75+
76+
local pattern = cairo.LinearPattern(0, 0, 10, 10)
77+
78+
### cairo.Context Path Iteration
79+
80+
The Cairo library offers iteration over drawing paths returned by the `cairo.Context.copy_path()` method. The resulting path can be iterated using the `:pairs()` method added to the `cairo.Path` class by LuaGObject. It returns an iterator suitable for use in Lua's for loop. For each item to be iterated on, it returns the type and an array table of either 0, 1, or 3 points. See this example of how to iterate on a path:
81+
82+
local path = cr:copy_path()
83+
for kind, points in path:pairs() do
84+
io.write(kind .. ":")
85+
for pt in ipairs(points) do
86+
io.write((" { %g, %g }"):format(pt.x, pt.y))
87+
end
88+
end
89+
90+
## Impact of Cairo on Other Libraries
91+
92+
In addition to Cairo itself, there are many Cairo-specific methods inside Gtk, Gdk, and Pango. LuaGObject wires them up in such a way that these libraries' cairo functions can be called naturally as if they were built into the Cairo core itself.
93+
94+
### Gdk and Gtk
95+
96+
`Gdk.Rectangle` is just a link to `cairo.RectangleInt` (similar to C, where `GdkRectangle` is just a typedef of `cairo_rectangle_int_t`). LuaGObject wires up `gdk_rectangle_union` and `gdk_rectangle_intersect` as methods of the `Gdk.Rectangle` class as expected.
97+
98+
`Gdk.cairo_create()` is aliased to `Gdk.Window.cairo_create()`. `Gdk.cairo_region_create_from_surface()` is aliased to `cairo.Region.create_from_surface()`.
99+
100+
`cairo.Context.set_source_rgba()` is overriden so that it also accepts a `Gdk.RGBA` instance as an argument. Similarly, `cairo.Context.rectangle()` alternatively accepts `Gdk.Rectangle` as an argument.
101+
102+
`cairo.Context` has a few additional methods, namely `get_clip_rectangle()`, `set_source_color()`, `set_source_pixbuf()`, `set_source_window()` and `set_source_region()`, implemented as calls to appropriate `Gdk.cairo_xxx` functions.
103+
104+
Since all of these extensions are implemented inside Gdk and Gtk libraries, they are present only when `LuaGObject.Gdk` is loaded. When loading just pure `LuaGObject.cairo`, they are not available.
105+
106+
### PangoCairo
107+
108+
The Pango font rendering library contains a namespace called `PangoCairo` which implements many Cairo-specific helper functions to integrate Pango with Cairo. It is possible to call them a global methods of the `PangoCairo` namespace, but LuaGObject also overrides these functions to make them available on Pango classes to which these methods logically belong.

docs/GLib-Variant.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# LuaGObject GVariant Support
2+
3+
LuaGObject provides extended overrides for supporting GLib's GVariant type. It supports the following operations with variants:
4+
5+
## Creation
6+
7+
Variants should be created using GLib.Variant(type, value) constructor. The `type` parameter is either GLib.VariantType or just a plain string describing requested type of the variant. These types are supported:
8+
9+
- `b`, `y`, `n`, `q`, `i`, `u`, `q`, `t`, `s`, `d`, `o`, `g` are basic types, see either GVariant's documentation or the DBus specification for their meaning. The `value` argument is expected to contain an appropriate string or number for the basic type.
10+
- `v` is the variant type, where `value` should be another GLib.Variant instance.
11+
- `m` is the 'maybe' type, where `value` should be either `nil` or a value acceptable for the target type.
12+
- `a` is an array of values of the specified type, where `value` is expected to contain a Lua table (array) with values for the array. If the array contains `nil` elements inside, it must contain also the `n` field with the real length of the array.
13+
- `(typelist)` is a tuple of types, where `value` is expected to contain a Lua table (array) with values for the tuple members.
14+
- `{key-value-pair}` is a dictionary entry, where `value` is expected to contain a Lua table (array) with 2 values (key and value) for the entry.
15+
16+
There are two convenience exceptions from above rules:
17+
18+
1. when an array of dictionary entries is given (i.e. a dictionary), `value` is expected to contain a Lua table with keys and values mapping to dictionary keys and values
19+
2. when an array of bytes is given, a bytestring is expected in the form of a Lua string, not an array of byte numbers.
20+
21+
Here are some examples to create valid variants:
22+
23+
GLib = require("LuaGObject").Glib
24+
local v1 = GLib.Variant("s", "Hello")
25+
local v2 = GLib.Variant("d", 3.14)
26+
local v3 = GLib.Variant("ms", nil)
27+
local v4 = GLib.Variant("v", v3)
28+
local v5 = GLib.Variant("as", { "Hello", "world" })
29+
local v6 = GLib.Variant("ami", { 1, nil, 2, n = 3 })
30+
local v7 = GLib.Variant("(is)", { 100, "title" })
31+
local v8 = GLib.Variant("a{sd}", { pi = 3.14, one = 1 })
32+
local v9 = GLib.Variant("aay", { "bytestring1", "bytestring2" })
33+
local v10 = GLib.Variant("(a{o(oayays)})",
34+
{{["/path/to/object1"]={"/path/to/object2",
35+
"bytestring1",
36+
"bytestring2",
37+
"string"}}})
38+
39+
## Data access
40+
41+
LuaGObject implements the following special properties for accessing data stored inside variants:
42+
43+
- `type` contains a read-only string describing the variant's type
44+
- `value` unpacks the value of the variant. Simple scalar types are unpacked into their corresponding Lua variants, tuples and dictionary entries are unpacked into Lua tables (arrays), child variants are expanded for `v`-typed variants. Dictionaries return a proxy table which can be indexed by dictionary keys to retrieve dictionary values. Generic arrays are __not__ automatically expanded, the source variants are returned instead.
45+
- The length operator `#` is overridden for GLib.Variants, returning number of child elements. Non-compound variants always return 0, and 'maybe's return 0 or 1. Arrays, tuples and dictionary entries return the number of children subvariants.
46+
- The numeric accessor operator `[number]` can index compound variants, returning the n-th subvariant (array entry, n-th field of tuple etc).
47+
- `pairs() and ipairs()` can accept Variants, which behave as expected.
48+
- contents of complex data types may be accessed using `get_child_value` method call.
49+
50+
Examples of extracting values from variants created above:
51+
52+
assert(v1.type == "s" and v1.value == "Hello")
53+
assert(v2.value == 3.14)
54+
assert(v3.value == nil and #v3 = 0)
55+
assert(v4.value == nil and #v4 = 1)
56+
assert(v5.value == v5 and #v5 == 2 and v5[2] == "world")
57+
assert(#v6 == 3 and v6[2] == nil)
58+
assert(v7.value[1] == 100 and v7[1] == 100 and #v7 == 2)
59+
assert(v8.value.pi == 3.14 and v8.value["one"] == 1 and #v8 == 2)
60+
assert(v9[1] == "bytestring1")
61+
assert(v10:get_child_value(0)
62+
:get_child_value(0)
63+
:get_child_value(1)
64+
:get_child_value(2).value == "bytestring2")
65+
for k, v in v8:pairs() do print(k, v) end
66+
67+
## Serialization
68+
69+
To serialize a variant into bytestream form, use the `data` property, which returns a Lua string containing the serialized variant. Deserialization is done by calling the `Variant.new_from_data` constructor, which is similar to `g_variant_new_from_data`, but it does _not_ accept a `destroy_notify` argument. See the following serialization example:
70+
71+
local v = GLib.Variant("s", "Hello")
72+
local serialized = v.data
73+
assert(type(data) == "string")
74+
75+
local newv = GLib.Variant.new_from_data(serialized, true)
76+
assert(newv.type == "s" and newv.value == "Hello")
77+
78+
## Other operations
79+
80+
LuaGObject also contains many of the original `g_variant_` APIs, but many of them are not necessary because their functionality is covered in a more Lua-native way by operations described above. However, there are still some useful calls, which are described here. All of them can be called using object notation on variant instances, e.g. `local vt = variant:get_type()`. See GLib's documentation for more detailed descriptions.
81+
82+
- `print(with_types)` returns a textual format of the variant. Note that LuaGObject does not contain opposite operation, i.e. g_variant_parse is not implemented yet.
83+
- `is_of_type(type)` checks whether a variant instance conforms to the specified type
84+
- `compare(other_variant)` and `equal(other_variant)` allow comparison of variant instances
85+
- `byteswap()`, `is_normal_form()`, and `get_normal_form()` for changing the underlying binary representation of variants.
86+
- `get_type()` returns a `VariantType` instance representing the type of the variant. It's seldom useful, as the `type` property returns the type as a string and is usually the better choice.
87+
- `GLib.VariantBuilder` is supported, but it is rarely useful as the creation of variant instances using constructors as noted above is usually preferred. An exception where `VariantBuilder` may be advisable is when creating very large arrays as creating a source Lua table might waste a lot of memory. Building such an array piece by piece using a `VariantBuilder` is often preferable. Not that `VariantBuilder`'s `end()` method clashes with Lua's `end` keyword, so LuaGObject renames it to `_end()`.
88+
- `VARIANT_TYPE_` constants are accessible as `GLib.VariantType.XXX`, e.g. `GLib.VariantType.STRING`. Although there should not be many cases where these constants are needed.

0 commit comments

Comments
 (0)