diff --git a/tests/test-selection-transfer.lua b/tests/test-selection-transfer.lua new file mode 100644 index 00000000..8a877720 --- /dev/null +++ b/tests/test-selection-transfer.lua @@ -0,0 +1,235 @@ +-- Test the selection ownership and transfer API + +local runner = require("_runner") +local spawn = require("awful.spawn") + +-- Assemble data for the large transfer that will be done later +local large_transfer_piece = "a" +for _ = 1, 25 do + large_transfer_piece = large_transfer_piece .. large_transfer_piece +end +large_transfer_piece = large_transfer_piece .. large_transfer_piece .. large_transfer_piece + +local large_transfer_piece_count = 3 +local large_transfer_size = #large_transfer_piece * large_transfer_piece_count + +local header = [[ +local lgi = require("lgi") +local Gdk = lgi.Gdk +local Gtk = lgi.Gtk +local GLib = lgi.GLib +local function assert_equal(a, b) + assert(a == b, + string.format("%s == %s", a or "nil/false", b or "nil/false")) +end +local clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) +]] + +local acquire_and_clear_clipboard = header .. [[ +clipboard:set_text("This is an experiment", -1) +GLib.idle_add(GLib.PRIORITY_DEFAULT, Gtk.main_quit) +Gtk.main() +]] + +local done_footer = [[ +io.stdout:write("done") +io.stdout:flush() +]] + +local check_targets_and_text = header .. [[ +local targets = clipboard:wait_for_targets() +assert_equal(targets[1]:name(), "TARGETS") +assert_equal(targets[2]:name(), "UTF8_STRING") +assert_equal(#targets, 2) +assert_equal(clipboard:wait_for_text(), "Hello World!") +]] .. done_footer + +local check_large_transfer = header + .. string.format("\nassert_equal(#clipboard:wait_for_text(), %d)\n", large_transfer_size) + .. done_footer + +local check_empty_selection = header .. [[ +assert_equal(clipboard:wait_for_targets(), nil) +assert_equal(clipboard:wait_for_text(), nil) +]] .. done_footer + +local selection +local selection_released +local continue + +local function wait_a_bit(count) + if continue or count == 5 then + return true + end +end + +runner.run_steps{ + function() + -- Get the selection + local s = assert(selection_acquire("CLIPBOARD"), + "Failed to acquire the clipboard selection") + + -- Steal selection ownership from ourselves and test that it works + local s_released + s:connect_signal("release", function() s_released = true end) + + selection = assert(selection_acquire("CLIPBOARD"), + "Failed to acquire the clipboard selection") + + assert(s_released) + + -- Now test selection transfers + selection = assert(selection_acquire("CLIPBOARD"), + "Failed to acquire the clipboard selection") + selection:connect_signal("request", function(_, target, transfer) + if target == "TARGETS" then + transfer:send{ + format = "atom", + data = { "TARGETS", "UTF8_STRING" }, + } + elseif target == "UTF8_STRING" then + transfer:send{ data = "Hello World!" } + end + end) + awesome.sync() + spawn.with_line_callback({ "lua", "-e", check_targets_and_text }, + { stdout = function(line) + assert(line == "done", "Unexpected line: " .. line) + continue = true + end }) + return true + end, + + function() + -- Wait for the test to succeed + if not continue then + return + end + continue = false + + -- Now test piece-wise selection transfers + selection = assert(selection_acquire("CLIPBOARD"), + "Failed to acquire the clipboard selection") + selection:connect_signal("request", function(_, target, transfer) + if target == "TARGETS" then + transfer:send{ + format = "atom", + data = { "TARGETS", "UTF8_STRING" }, + } + elseif target == "UTF8_STRING" then + local offset = 1 + local data = "Hello World!" + local function send_piece() + local piece = data:sub(offset, offset) + transfer:send{ + data = piece, + continue = piece ~= "" + } + offset = offset + 1 + end + transfer:connect_signal("continue", send_piece) + send_piece() + end + end) + awesome.sync() + spawn.with_line_callback({ "lua", "-e", check_targets_and_text }, + { stdout = function(line) + assert(line == "done", "Unexpected line: " .. line) + continue = true + end }) + return true + end, + + function() + -- Wait for the test to succeed + if not continue then + return + end + continue = false + + -- Now test a huge transfer + selection = assert(selection_acquire("CLIPBOARD"), + "Failed to acquire the clipboard selection") + selection:connect_signal("request", function(_, target, transfer) + if target == "TARGETS" then + transfer:send{ + format = "atom", + data = { "TARGETS", "UTF8_STRING" }, + } + elseif target == "UTF8_STRING" then + local count = 0 + local function send_piece() + count = count + 1 + local done = count == large_transfer_piece_count + transfer:send{ + data = large_transfer_piece, + continue = not done, + } + end + transfer:connect_signal("continue", send_piece) + send_piece() + end + end) + awesome.sync() + spawn.with_line_callback({ "lua", "-e", check_large_transfer }, + { stdout = function(line) + assert(line == "done", "Unexpected line: " .. line) + continue = true + end }) + return true + end, + + wait_a_bit, + wait_a_bit, + wait_a_bit, + wait_a_bit, + wait_a_bit, + + function() + -- Wait for the test to succeed + if not continue then + return + end + continue = false + + -- Now test that :release() works + selection:release() + awesome.sync() + spawn.with_line_callback({ "lua", "-e", check_empty_selection }, + { stdout = function(line) + assert(line == "done", "Unexpected line: " .. line) + continue = true + end }) + + return true + end, + + function() + -- Wait for the test to succeed + if not continue then + return + end + continue = false + + -- Test for "release" signal when we lose selection + selection = assert(selection_acquire("CLIPBOARD"), + "Failed to acquire the clipboard selection") + selection:connect_signal("release", function() selection_released = true end) + awesome.sync() + spawn.with_line_callback({ "lua", "-e", acquire_and_clear_clipboard }, + { exit = function() continue = true end }) + return true + end, + + function() + -- Wait for the previous test to succeed + if not continue then + return + end + continue = false + assert(selection_released) + return true + end, +} + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80