diff --git a/X-kutu.c b/X-kutu.c index 79a2724..34c40ec 100644 --- a/X-kutu.c +++ b/X-kutu.c @@ -225,8 +225,17 @@ Event wait_for_event(void) { case XCB_MAP_NOTIFY: { xcb_map_notify_event_t *e; e = (xcb_map_notify_event_t *)ev; + ret.type = -1; + ret.window = e->window; + ret.override_redirect = e->override_redirect; + } break; + + case XCB_MAP_REQUEST: { + xcb_map_request_event_t *e; + e = (xcb_map_request_event_t *)ev; ret.type = 4; ret.window = e->window; + ret.override_redirect = 1; } break; case XCB_BUTTON_PRESS: { diff --git a/compile.sh b/compile.sh index 725ab59..3228c4b 100755 --- a/compile.sh +++ b/compile.sh @@ -8,8 +8,8 @@ if ! XCB=$(pkg-config --cflags --libs xcb 2>/dev/null); then exit 1 fi -if ! xrandr --version >/dev/null; then - echo "Error: xrandr not found. Please install xrandr." >&2 +if ! xrandr --version >/dev/null 2>&1 || ! xprop -version >/dev/null 2>&1; then + echo "Error: xrandr or xprop not found. Please install xrandr and xprop." >&2 exit 1 fi diff --git a/kutu.rb b/kutu.rb index 88b31f5..693062f 100755 --- a/kutu.rb +++ b/kutu.rb @@ -57,16 +57,29 @@ at_exit { X.cleanup } $monitors = {} -xrandr_output = `xrandr --query` -connected = xrandr_output.each_line.select { |line| line.include?(" connected") } -connected.sort_by! { |line| line.include?(" primary") ? 0 : 1 } -connected.first(2).each_with_index do |line, index| - next unless line =~ /(\d+)x(\d+)\+(\d+)\+(\d+)/ - w, h, x, y = $1.to_i, $2.to_i, $3.to_i, $4.to_i - key = index.zero? ? :primary : :secondary - $monitors[key] = { x: x, y: y, width: w, height: h } +def refresh_monitors + $monitors.clear + xrandr_output = `xrandr --query` + connected = xrandr_output.each_line.select { |line| line.include?(" connected") } + connected.sort_by! { |line| line.include?(" primary") ? 0 : 1 } + connected.first(2).each_with_index do |line, index| + next unless line =~ /(\d+)x(\d+)\+(\d+)\+(\d+)/ + w, h, x, y = $1.to_i, $2.to_i, $3.to_i, $4.to_i + key = index.zero? ? :primary : :secondary + $monitors[key] = { x: x, y: y, width: w, height: h } + end end +refresh_monitors + +# def get_wm_normal_hints(window_id) +# xprop_output = `xprop -id 0x#{window_id.to_s(16)} WM_NORMAL_HINTS` +# return {} unless xprop_output =~ /WM_NORMAL_HINTS\(([^)]+)\):\s*(.*)/ +# hints = {} +# # TODO: parse the output properly +# hints +# end + $workspaces = {} $windows = {} @@ -92,10 +105,12 @@ class Node end class Window < Node - attr_accessor :window_id, :x, :y, :width, :height + attr_accessor :window_id, :x, :y, :width, :height#, :state def initialize(window_id) @window_id = window_id + # @state = :widthrawn # :iconic, :withdrawn, :normal + # ADD: properties for https://tronche.com/gui/x/icccm/sec-4.html#s-4 sec 4.1.2.(3, 4) super() end @@ -226,6 +241,7 @@ EVENT_TYPES = { 1 => :create, 2 => :close, 3 => :enter, + -1 => :show_after, 4 => :show, 5 => :mouse_press, 6 => :mouse_drag, @@ -265,21 +281,22 @@ loop do event = X.wait_for_event case EVENT_TYPES[event[:type]] when :create - if event[:override_redirect].zero? - X.subscribe event[:window] - X.focus event[:window] - end + next unless event[:override_redirect].zero? + X.subscribe event[:window] + X.focus event[:window] when :close X.kill event[:window] $windows[event[:window]]&.remove event[:window] when :enter X.focus event[:window] X.send_to_top event[:window] - when :show - X.show event[:window] + when :show_after + next unless event[:override_redirect].zero? X.focus event[:window] $workspaces[:main].add event[:window] if $windows[event[:window]].nil? $workspaces[:main].tiled_root_block.compute_geometry! + when :show + X.show event[:window] when :mouse_press next if event[:is_root] != 0 X.send_to_top event[:window] diff --git a/list.tmp b/list.tmp new file mode 100644 index 0000000..9d99ddb --- /dev/null +++ b/list.tmp @@ -0,0 +1,40 @@ +#define XCB_KEY_PRESS 2 +#define XCB_KEY_RELEASE 3 + +#define XCB_BUTTON_PRESS 4 +#define XCB_BUTTON_RELEASE 5 +#define XCB_MOTION_NOTIFY 6 + +#define XCB_ENTER_NOTIFY 7 + +#define XCB_LEAVE_NOTIFY 8 - maybe + +#define XCB_CREATE_NOTIFY 16 + +// treat these similarly +#define XCB_DESTROY_NOTIFY 17 // to remove from struct +#define XCB_UNMAP_NOTIFY 18 // i guess this is minimize but idk if it is icccm IconicState? + +#define XCB_MAP_NOTIFY 19 // whatever im doin (dont map this is after mapping) + +#define XCB_MAP_REQUEST 20 // Actual request to map // so map the window if possible + +#define XCB_CONFIGURE_REQUEST 23 // for floats maybe +#define XCB_GRAVITY_NOTIFY 24 // similar to XCB_CONFIGURE_NOTIFY but for pos +#define XCB_RESIZE_REQUEST 25 // similar to XCB_CONFIGURE_REQUEST but for resize + +#define XCB_CONFIGURE_NOTIFY 22 // prolly remove it +#define XCB_PROPERTY_NOTIFY 28 // only if netwm requires so +#define XCB_CLIENT_MESSAGE 33 // only if netwm requires + + +-- ICCCM +// TODO: add a function to set wm_state. +// actually no as there is no iconfied state .. all windows are maximized and ignore any client request to be iconfied +// therefore break ICCCM + +// use xprop to get +// WM_NAME .. then ignore it cuz no titlebars + +// WM_NORMAL_HINTS & WM_HINTS +// try to obey it for floats