Cleanups, more automated lookups of atoms to avoid needing to dereference constants.

More constants and requestsm including SendEvent, and
a helper for ClientMessage, w/example
This commit is contained in:
Vidar Hokstad 2024-01-11 19:24:49 +00:00
parent 5f3aca393e
commit da2fe51596
5 changed files with 100 additions and 35 deletions

13
example/client_message.rb Normal file
View file

@ -0,0 +1,13 @@
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
require 'X11'
display = X11::Display.new
display.client_message(
mask: X11::Form::SubstructureNotifyMask | X11::Form::SubstructureRedirectMask,
type: :_NET_CURRENT_DESKTOP,
data: ARGV.shift.to_i
)

View file

@ -316,6 +316,12 @@ module X11
def atom(name)
return name if name.is_a?(Integer) # Allow atom(atom_integer_or_symbol)
begin
return Form::Atoms.const_get(name.to_sym) if Form::Atoms.const_defined?(name.to_sym)
rescue
# const_defined? will throw if name isn't a valid constant name, but
# that's fine
end
name = name.to_sym
intern_atom(false, name) if !@atoms[name]
@atoms[name]
@ -404,7 +410,10 @@ module X11
def u8(*args) = args.pack("c*")
def u16(*args) = args.pack("v*")
def u32(*args) = args.pack("V*")
def atom_enum(val) = open_enum(val, {cardinal: Form::CardinalAtom, atom: Form::AtomAtom, window: Form::WindowAtom})
def atom_enum(val)
open_enum(val, {cardinal: Form::CardinalAtom, atom: Form::AtomAtom, window: Form::WindowAtom}) || atom(val)
end
def window(*args)
args.each {|a| raise "Window expected" if a.nil? }
u32(*args)
@ -415,7 +424,7 @@ module X11
def set_input_focus(revert_to, focus, time=:now)
# FIXME: This is an experiment.
# Upside: Simpler. Downside: Doesn't work server-side.
#
# Probably a bad idea.
revert_to = open_enum(revert_to, {none: 0, pointer_root: 1, parent: 2})
focus = open_enum(focus, {none: 0, pointer_root: 1 })
time = open_enum(time, {current_time: 0, now: 0})
@ -455,9 +464,8 @@ module X11
def configure_window(window, x: nil, y: nil, width: nil, height: nil,
border_width: nil, sibling: nil, stack_mode: nil)
mask = 0
values = []
mask = 0
mask |= set_value(values, 0x001, x)
mask |= set_value(values, 0x002, y)
mask |= set_value(values, 0x004, width)
@ -480,7 +488,9 @@ module X11
end
def create_gc(window, foreground: nil, background: nil)
def create_gc(window, foreground: nil, background: nil,
graphics_exposures: nil
)
mask = 0
args = []
@ -489,12 +499,27 @@ module X11
# https://tronche.com/gui/x/xlib/GC/manipulating.html#XGCValues
mask |= set_value(args, 0x04, foreground)
mask |= set_value(args, 0x08, background)
mask |= set_value(args, 0x10000, graphics_exposures)
gc = new_id
write_request(X11::Form::CreateGC.new(gc, window, mask, args))
gc
end
def send_event(...) = write_request(Form::SendEvent.new(...))
def client_message(window: default_root, type: :ClientMessage, format: 32, destination: default_root, mask: 0, data: [], propagate: true)
f = {8 => "C20", 16 => "S10", 32 => "L5"}[format]
p f
data = (Array(data).map{|item|atom(item)} +[0]*20).pack(f)
event = Form::ClientMessage.new(
format, 0, window, atom(type), data
)
event.code =33
pp event
send_event(propagate, destination, mask, event)
end
def put_image(*args) = write_request(X11::Form::PutImage.new(*args))
def clear_area(*args) = write_request(X11::Form::ClearArea.new(*args))
def copy_area(*args) = write_request(X11::Form::CopyArea.new(*args))
@ -560,19 +585,19 @@ module X11
end
when :rgb24
@rgb24 ||= formats.formats.find do |f|
f.type == 1 &&
f.type == 1 &&
f.depth == 24 &&
f.direct.red == 16 &&
f.direct.green == 8 &&
f.direct.green == 8 &&
f.direct.blue == 0
end
when :argb24
@argb24 ||= formats.formats.find do |f|
f.type == 1 &&
f.type == 1 &&
f.depth == 32 &&
f.direct.alpha == 24 &&
f.direct.red == 16 &&
f.direct.green == 8 &&
f.direct.green == 8 &&
f.direct.blue == 0
end
else

View file

@ -184,6 +184,29 @@ module X11
end
end
# # Predefined constants, that can be used in the form of symbols
module Atoms
PRIMARY = 1
SECONDARY = 2
ARC = 3
ATOM = 4
BITMAP = 5
CARDINAL = 6
COLORMAP = 7
CURSOR = 8
#...
STRING = 31
VISUALID = 32
WINDOW = 33
WM_COMMAND = 34
WM_HINTS = 35
end
PointerWindow = 0
InputFocus = 1
# FIXME: Deprecated in favour of the Constants module
AtomAtom=4
CardinalAtom=6
WindowAtom=33
@ -286,6 +309,9 @@ module X11
field :minor_opcode, Uint16
field :major_opcode, Uint8
unused 21
# The original request
attr_accessor :request
end
# XRender structures
@ -329,8 +355,9 @@ module X11
field :colormap, Colormap
end
# Requests
# # Requests
# Constants, p112 onwards
CopyFromParent = 0
InputOutput = 1
InputOnly = 2
@ -358,12 +385,17 @@ module X11
PointerMotionMask = 0x000040
PointerMotionHintMask = 0x000080
Button1MotionMask = 0x000100
# 0x200 .. 0x40000; page 113
ExposureMask = 0x008000
VisibilityChangeMask = 0x010000
StructureNotifyMask = 0x020000
ResizeRedirectMask = 0x040000
SubstructureNotifyMask = 0x080000
SubstructureRedirectMask=0x100000
FocusChangeMask = 0x200000
PropertyChangeMask = 0x400000
ColormapChangeMask = 0x800000
OwnerGrabButtonMask = 0x100000
class CreateWindow < BaseForm
field :opcode, Uint8, value: 1
@ -592,6 +624,15 @@ module X11
field :value, String8, :string
end
class SendEvent < BaseForm
field :opcode, Uint8, value: 25
field :propagate, Bool
field :request_length, Uint16, value: 11
field :destination, Window
field :event_mask, Uint32
field :event, Uint32 # FIXME: This is wrong, and will break on parsing.
end
class GrabButton < BaseForm
field :opcode, Uint8, value: 28
field :owner_events, Bool
@ -678,6 +719,7 @@ module X11
ForegroundMask = 0x04
BackgroundMask = 0x08
FontMask = 0x4000
GraphicsExposures = 0x10000
class CreateGC < BaseForm
field :opcode, Uint8, value: 55
@ -1002,6 +1044,7 @@ module X11
unused 1
field :sequence_number, Uint16
field :event, Window
field :window, Window
field :above_sibling, Window
field :x, Int16
field :y, Int16

View file

@ -1,14 +1,12 @@
module X11
module Protocol
# endiness of your machine
# endianess of your machine
BYTE_ORDER = case [1].pack("L")
when "\0\0\0\1"
"B".ord
when "\1\0\0\0"
"l".ord
when "\0\0\0\1" then "B".ord
when "\1\0\0\0" then "l".ord
else
raise ByteOrderError.new "Cannot determine byte order"
end
end
MAJOR = 11
MINOR = 0

View file

@ -7,25 +7,11 @@ module X11
@internal = data
end
def root
@internal.root
end
def root_depth
@internal.root_depth
end
def root_visual
@internal.root_visual
end
def width
@internal.width_in_pixels
end
def height
@internal.height_in_pixels
end
def root = @internal.root
def root_depth = @internal.root_depth
def root_visual = @internal.root_visual
def width = @internal.width_in_pixels
def height = @internal.height_in_pixels
def to_s
"#<X11::Screen(#{id}) width=#{width} height=#{height}>"