Skip to content

Instantly share code, notes, and snippets.

@tmtm
Created December 26, 2021 16:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tmtm/f9642c3ea740edf87f04940cc57f9b0f to your computer and use it in GitHub Desktop.
Save tmtm/f9642c3ea740edf87f04940cc57f9b0f to your computer and use it in GitHub Desktop.
X のウィンドウのクラスとタイトルを取得する
require 'ffi'
module FFI
typedef :pointer, :Display
typedef :ulong, :XID
typedef :XID, :Window
typedef :int, :Status
typedef :ulong, :Atom
end
class XClassHint < FFI::Struct
layout(
:name, :pointer,
:class, :pointer,
)
end
class XTextProperty < FFI::Struct
layout(
:value, :pointer,
:encoding, :Atom,
:format, :int,
:nitems, :ulong,
)
end
module X11
extend FFI::Library
ffi_lib 'X11'
attach_function :XOpenDisplay, [:string], :Display
attach_function :XGetInputFocus, [:Display, :pointer, :pointer], :int
attach_function :XGetClassHint, [:Display, :Window, XClassHint.by_ref], :int
attach_function :XQueryTree, [:Display, :Window, :pointer, :pointer, :pointer, :pointer], :Status
attach_function :XGetWMName, [:Display, :Window, XTextProperty.by_ref], :void
attach_function :Xutf8TextPropertyToTextList, [:Display, XTextProperty.by_ref, :pointer, :pointer], :int
attach_function :XFree, [:pointer], :int
attach_function :XFreeStringList, [:pointer], :void
end
display = X11.XOpenDisplay(nil)
raise "Cannot open display: #{ENV['DISPLAY']}" if display.null?
root = FFI::MemoryPointer.new(:Window)
parent = FFI::MemoryPointer.new(:Window)
children = FFI::MemoryPointer.new(:pointer)
nchildren = FFI::MemoryPointer.new(:int)
focus_win = FFI::MemoryPointer.new(:Window)
revert_to = FFI::MemoryPointer.new(:int)
text_list = FFI::MemoryPointer.new(:pointer)
count = FFI::MemoryPointer.new(:int)
loop do
X11.XGetInputFocus(display, focus_win, revert_to)
window = focus_win.read(:Window)
class_hint = XClassHint.new
while window > 0
X11.XGetClassHint(display, window, class_hint)
X11.XQueryTree(display, window, root, parent, children, nchildren)
X11.XFree(children.read_pointer)
break unless class_hint[:name].null? && class_hint[:class].null?
window = parent.read(:Window)
end
prop = XTextProperty.new
prop[:encoding] = 1
X11.XGetWMName(display, window, prop)
X11.Xutf8TextPropertyToTextList(display, prop, text_list, count)
win_name = class_hint[:name].read_string
win_class = class_hint[:class].read_string
title = text_list.read(:pointer).read(:pointer).read_string.force_encoding('utf-8')
p [win_class, title]
X11.XFree(class_hint[:name]) unless class_hint[:name].null?
X11.XFree(class_hint[:class]) unless class_hint[:class].null?
X11.XFreeStringList(text_list.read(:pointer))
sleep 0.1
end
@tmtm
Copy link
Author

tmtm commented Jan 10, 2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment