Class: XlibObj::Window

Inherits:
Object
  • Object
show all
Defined in:
lib/window.rb,
lib/window/property.rb,
lib/window/event_handler.rb

Defined Under Namespace

Classes: EventHandler, Property

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(display, window_id) ⇒ Window

Returns a new instance of Window.



11
12
13
14
15
# File 'lib/window.rb', line 11

def initialize(display, window_id)
  @display = display
  @to_native = window_id
  @event_handler = EventHandler.singleton(display, self)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name) ⇒ Object



29
30
31
# File 'lib/window.rb', line 29

def method_missing(name)
  attribute(name)
end

Instance Attribute Details

#displayObject (readonly)

Queries



18
19
20
# File 'lib/window.rb', line 18

def display
  @display
end

#to_nativeObject (readonly) Also known as: id

Queries



18
19
20
# File 'lib/window.rb', line 18

def to_native
  @to_native
end

Instance Method Details

#absolute_positionObject



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/window.rb', line 41

def absolute_position
  x_abs = FFI::MemoryPointer.new :int
  y_abs = FFI::MemoryPointer.new :int
  child = FFI::MemoryPointer.new :Window
  root_win = screen.root_window

  Xlib.XTranslateCoordinates(@display.to_native, @to_native, root_win.to_native, 0, 0, x_abs,
    y_abs, child)

  { x: x_abs.read_int, y: y_abs.read_int }
end

#attribute(name) ⇒ Object



21
22
23
24
25
26
27
# File 'lib/window.rb', line 21

def attribute(name)
  attributes = Xlib::WindowAttributes.new
  Xlib.XGetWindowAttributes(@display.to_native, @to_native, attributes.pointer)
  attributes[name.to_sym]
rescue
  nil
end

#create_input_windowObject



209
210
211
212
213
214
# File 'lib/window.rb', line 209

def create_input_window
  attributes = Xlib::SetWindowAttributes.new
  win_id = Xlib.XCreateWindow(@display.to_native, to_native, 0, 0, 1, 1, 0, Xlib::CopyFromParent,
    Xlib::InputOnly, nil, 0, attributes.pointer)
  Window.new(@display, win_id)
end

#create_windowObject



203
204
205
206
207
# File 'lib/window.rb', line 203

def create_window
  black = Xlib.XBlackPixel(@display.to_native, 0)
  win_id = Xlib.XCreateSimpleWindow(@display.to_native, to_native, 0, 0, 1, 1, 0, black, black)
  Window.new(@display, win_id)
end

#delete_property(name) ⇒ Object



65
66
67
# File 'lib/window.rb', line 65

def delete_property(name)
  Property.new(self, name).delete
end

#destroyObject



216
217
218
219
# File 'lib/window.rb', line 216

def destroy
  finalize
  Xlib.XDestroyWindow(@display.to_native, to_native)
end

#finalizeObject



221
222
223
# File 'lib/window.rb', line 221

def finalize
  @event_handler.destroy
end

#focusObject



99
100
101
102
103
# File 'lib/window.rb', line 99

def focus
  Xlib.XSetInputFocus(@display.to_native, @to_native, Xlib::RevertToParent, Xlib::CurrentTime)
  Xlib::X.flush(@display)
  self
end

#focused?Boolean

Returns:

  • (Boolean)


53
54
55
56
57
58
# File 'lib/window.rb', line 53

def focused?
  focused_window = FFI::MemoryPointer.new :Window
  focus_state = FFI::MemoryPointer.new :int
  Xlib.XGetInputFocus(@display.to_native, focused_window, focus_state)
  focused_window.read_int == @to_native
end

#handle(event) ⇒ Object



120
121
122
123
# File 'lib/window.rb', line 120

def handle(event)
  @event_handler.handle(event)
  self
end

#iconifyObject



87
88
89
90
91
# File 'lib/window.rb', line 87

def iconify
  Xlib.XIconifyWindow(@display.to_native, @to_native, screen.number)
  Xlib::X.flush(@display)
  self
end

#inspectObject



225
226
227
# File 'lib/window.rb', line 225

def inspect
  "#<#{self.class.name}:0x#{'%014x' % __id__} @id=#{id}>"
end

#mapObject



75
76
77
78
79
# File 'lib/window.rb', line 75

def map
  Xlib.XMapWindow(@display.to_native, @to_native)
  Xlib::X.flush(@display)
  self
end

#move_resize(x, y, width, height) ⇒ Object



69
70
71
72
73
# File 'lib/window.rb', line 69

def move_resize(x, y, width, height)
  Xlib.XMoveResizeWindow(@display.to_native, @to_native, x, y, width, height)
  Xlib::X.flush(@display)
  self
end

#off(mask, type, callback = nil) ⇒ Object



115
116
117
118
# File 'lib/window.rb', line 115

def off(mask, type, callback = nil)
  @event_handler.off(mask, type, callback)
  self
end

#on(mask, type, &callback) ⇒ Object



105
106
107
# File 'lib/window.rb', line 105

def on(mask, type, &callback)
  @event_handler.on(mask, type, &callback)
end

#property(name) ⇒ Object



37
38
39
# File 'lib/window.rb', line 37

def property(name)
  Property.new(self, name).get
end

#raiseObject



93
94
95
96
97
# File 'lib/window.rb', line 93

def raise
  Xlib.XRaiseWindow(@display.to_native, @to_native)
  Xlib::X.flush(@display)
  self
end

#request_selection(type = :PRIMARY, target: :UTF8_STRING, property: :XSEL_DATA, &on_receive) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/window.rb', line 130

def request_selection(type = :PRIMARY, target: :UTF8_STRING, property: :XSEL_DATA, &on_receive)
  # will only receive the selection notify event, if the window has been created by the process
  # running this very code
  until_true(:no_event, :selection_notify) do |event|
    break false if Atom.new(@display, event.selection).name != type
    break false if Atom.new(@display, event.target).name != target

    # query selection content
    if event.property == Xlib::None
      selection = nil
    else
      selection = property(event.property)
      delete_property(event.property)
    end

    # send selection to callback
    selection_owner = Window.new(@display, Xlib.XGetSelectionOwner(@display.to_native, event.selection))
    on_receive.call(selection, type, selection_owner)

    true
  end

  # request the selection
  type_atom = Atom.new(@display, type)
  target_atom = Atom.new(@display, target)
  property_atom = Atom.new(@display, property)
  Xlib.XConvertSelection(@display.to_native, type_atom.to_native, target_atom.to_native,
    property_atom.to_native, @to_native, Xlib::CurrentTime)
  Xlib::X.flush(@display)

  self
end

#screenObject



33
34
35
# File 'lib/window.rb', line 33

def screen
  Screen.new(@display, attribute(:screen))
end

#send_to_itself(type, data = nil, subject = nil) ⇒ Object



125
126
127
128
# File 'lib/window.rb', line 125

def send_to_itself(type, data = nil, subject = nil)
  Event::ClientMessage.new(type, data, subject).send_to(self)
  self
end

#set_property(name, value, type = nil) ⇒ Object

Commands



61
62
63
# File 'lib/window.rb', line 61

def set_property(name, value, type = nil)
  Property.new(self, name).set(value, type)
end

#set_selection(type = :PRIMARY, targets: [:UTF8_STRING, :STRING, :TEXT], &on_request) ⇒ Object



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/window.rb', line 163

def set_selection(type = :PRIMARY, targets: [:UTF8_STRING, :STRING, :TEXT], &on_request)
  type_atom = Atom.new(@display, type)
  Xlib.XSetSelectionOwner(@display.to_native, type_atom.to_native, to_native, Xlib::CurrentTime)

  request_handler = on(:no_event, :selection_request) do |event|
    break if Atom.new(@display, event.selection).name != type

    # convert selection
    target = Atom.new(@display, event.target).name
    selection = if target == :TARGETS
                  (targets + [:TARGETS]).map{ |t| Atom.new(@display, t) }
                elsif targets.include? target
                  on_request.call(target)
                end

    # set property on requestor
    requestor = Window.new(@display, event.requestor)
    if selection
      property = event.property == Xlib::None ? event.target : event.property
      requestor.set_property(property, selection)

      # notify requestor of set property
      Event::SelectionNotify.new(type: event.selection, target: event.target, property: property).
        send_to(requestor)
    else
      # notify requestor of failed conversion
      Event::SelectionNotify.new(type: event.selection, target: event.target, property: Xlib::None).
        send_to(requestor)
    end
  end

  until_true(:no_event, :selection_clear) do |event|
    break false if Atom.new(@display, event.selection).name != type
    off(:no_event, :selection_request, request_handler)
    true
  end

  self
end

#unmapObject



81
82
83
84
85
# File 'lib/window.rb', line 81

def unmap
  Xlib.XUnmapWindow(@display.to_native, @to_native)
  Xlib::X.flush(@display)
  self
end

#until_true(mask, type, &callback) ⇒ Object



109
110
111
112
113
# File 'lib/window.rb', line 109

def until_true(mask, type, &callback)
  handler = on(mask, type) do |*args|
    off(mask, type, handler) if callback.call(*args)
  end
end