From 2bcdbf7b0f9348dd5a068c3ca5ed12dcf1c518eb Mon Sep 17 00:00:00 2001 From: Robert Ancell Date: Wed, 7 Dec 2022 13:07:31 +1300 Subject: [PATCH] Detect window deletion --- example/window.dart | 17 ++++++++++++++++- lib/src/x11_client.dart | 17 +++++++++++------ lib/src/x11_events.dart | 42 ++++++++++++++++++++++++++++++++++------- lib/src/x11_types.dart | 3 +++ 4 files changed, 65 insertions(+), 14 deletions(-) diff --git a/example/window.dart b/example/window.dart index 9a185b7..6c913b6 100644 --- a/example/window.dart +++ b/example/window.dart @@ -4,7 +4,10 @@ void main() async { var client = X11Client(); await client.connect(); - client.eventStream.listen((event) { + var wmProtocolsAtom = await client.internAtom('WM_PROTOCOLS'); + var wmDeleteWindowAtom = await client.internAtom('WM_DELETE_WINDOW'); + + client.eventStream.listen((event) async { if (event is X11KeyPressEvent) { print('KeyPress ${event.key}'); } else if (event is X11KeyReleaseEvent) { @@ -25,6 +28,12 @@ void main() async { print('FocusOut'); } else if (event is X11ExposeEvent) { client.clearArea(event.window, event.area); + } else if (event is X11ClientMessageEvent) { + if (event.type == wmProtocolsAtom) { + if (X11Atom(event.data[0]) == wmDeleteWindowAtom) { + await client.close(); + } + } } }); @@ -43,6 +52,12 @@ void main() async { X11EventType.focusChange }, backgroundPixel: 0x00000000); + + // Set window title. await client.changePropertyString(id, 'WM_NAME', 'x11.dart'); + + // Make able to detect when window is closed. + await client.changePropertyAtom(id, 'WM_PROTOCOLS', ['WM_DELETE_WINDOW']); + client.mapWindow(id); } diff --git a/lib/src/x11_client.dart b/lib/src/x11_client.dart index 4dc6b70..5918943 100644 --- a/lib/src/x11_client.dart +++ b/lib/src/x11_client.dart @@ -662,10 +662,14 @@ class X11Client { /// Changes a [property] of [window] to [value]. Future changePropertyAtom( - X11ResourceId window, String property, String value, + X11ResourceId window, String property, List value, {X11ChangePropertyMode mode = X11ChangePropertyMode.replace}) async { - var valueAtom = await internAtom(value); - return await changePropertyUint32(window, property, [valueAtom.value], + var valueAtoms = []; + for (var name in value) { + var atom = await internAtom(name); + valueAtoms.add(atom.value); + } + return await changePropertyUint32(window, property, valueAtoms, type: 'ATOM', mode: mode); } @@ -1946,7 +1950,8 @@ class X11Client { } } } else { - var code = reply; + //var fromSendEvent = reply & 0x80 != 0; + var code = reply & 0x7f; var eventBuffer = X11ReadBuffer(); eventBuffer.add(_buffer.readUint8()); _buffer.readUint16(); // FIXME(robert-ancell): sequenceNumber @@ -2016,8 +2021,8 @@ class X11Client { event = X11SelectionNotifyEvent.fromBuffer(eventBuffer); } else if (code == 32) { event = X11ColormapNotifyEvent.fromBuffer(eventBuffer); - /*} else if (code == 33) { - event = X11ClientMessageEvent.fromBuffer(eventBuffer);*/ + } else if (code == 33) { + event = X11ClientMessageEvent.fromBuffer(eventBuffer); } else if (code == 34) { event = X11MappingNotifyEvent.fromBuffer(eventBuffer); } diff --git a/lib/src/x11_events.dart b/lib/src/x11_events.dart index ade51fa..dba0a7f 100644 --- a/lib/src/x11_events.dart +++ b/lib/src/x11_events.dart @@ -1165,20 +1165,42 @@ class X11ColormapNotifyEvent extends X11Event { } } -/*class X11ClientMessageEvent extends X11Event { +class X11ClientMessageEvent extends X11Event { final int format; final X11ResourceId window; final X11Atom type; - final ?ClientMessageData? data; + final List data; - X11ClientMessageEvent(this.format, this.window, this.type, this.data); + X11ClientMessageEvent.uint8(this.window, this.type, this.data) : format = 8 { + assert(data.length == 20); + } + + X11ClientMessageEvent.uint16(this.window, this.type, this.data) + : format = 16 { + assert(data.length == 10); + } + + X11ClientMessageEvent.uint32(this.window, this.type, this.data) + : format = 32 { + assert(data.length == 5); + } factory X11ClientMessageEvent.fromBuffer(X11ReadBuffer buffer) { var format = buffer.readUint8(); var window = buffer.readResourceId(); var type = buffer.readAtom(); - var data = buffer.read?ClientMessageData?(); - return X11ClientMessageEvent(format, window, type, data); + if (format == 8) { + return X11ClientMessageEvent.uint8( + window, type, buffer.readListOfUint8(20)); + } else if (format == 16) { + return X11ClientMessageEvent.uint16( + window, type, buffer.readListOfUint16(10)); + } else if (format == 32) { + return X11ClientMessageEvent.uint32( + window, type, buffer.readListOfUint32(5)); + } else { + throw Exception('Invalid ClientMessage format $format'); + } } @override @@ -1186,10 +1208,16 @@ class X11ColormapNotifyEvent extends X11Event { buffer.writeUint8(format); buffer.writeResourceId(window); buffer.writeAtom(type); - buffer.write?ClientMessageData?(data); + if (format == 8) { + buffer.writeListOfUint8(data); + } else if (format == 16) { + buffer.writeListOfUint16(data); + } else if (format == 32) { + buffer.writeListOfUint32(data); + } return 33; } -}*/ +} class X11MappingNotifyEvent extends X11Event { final int request; diff --git a/lib/src/x11_types.dart b/lib/src/x11_types.dart index daa4546..349ec3a 100644 --- a/lib/src/x11_types.dart +++ b/lib/src/x11_types.dart @@ -376,6 +376,9 @@ class X11Atom { @override String toString() => 'X11Atom($value)'; + + @override + bool operator ==(other) => other is X11Atom && other.value == value; } class X11CharacterInfo {