{"id":17477694,"url":"https://github.com/moaxcp/x11","last_synced_at":"2025-04-13T18:22:20.176Z","repository":{"id":57721593,"uuid":"262675241","full_name":"moaxcp/x11","owner":"moaxcp","description":"An x11 protocol implementation and client for the jvm","archived":false,"fork":false,"pushed_at":"2024-08-09T02:58:23.000Z","size":2159,"stargazers_count":18,"open_issues_count":10,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-18T23:18:06.977Z","etag":null,"topics":["desktop","java","x11","xlib"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/moaxcp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-09T23:11:53.000Z","updated_at":"2024-09-03T00:40:49.000Z","dependencies_parsed_at":"2024-03-13T23:24:11.256Z","dependency_job_id":"f2294d58-657f-42fb-9013-6c1175ff5397","html_url":"https://github.com/moaxcp/x11","commit_stats":{"total_commits":207,"total_committers":1,"mean_commits":207.0,"dds":0.0,"last_synced_commit":"14817b2b3de3e959a60aee52794894ddba07c8a7"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moaxcp%2Fx11","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moaxcp%2Fx11/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moaxcp%2Fx11/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moaxcp%2Fx11/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/moaxcp","download_url":"https://codeload.github.com/moaxcp/x11/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248759134,"owners_count":21157096,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["desktop","java","x11","xlib"],"created_at":"2024-10-18T20:08:57.364Z","updated_at":"2025-04-13T18:22:20.155Z","avatar_url":"https://github.com/moaxcp.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# x11\n\nx11 enables java and other jvm languages to talk directly to a x11 \nserver without binding to a C library. The client is similar to X11lib for C\nbut uses objects to represent the protocol resulting in a simplified client. It \nsupports the core protocol and all extensions. The client follows the same pattern \nas X11lib by queuing one-way requests before sending them to the server. The\nx11-protocol project enables reading and writing the entire protocol and can\nbe used to help write a x11 server.\n\n[![Java CI with Gradle](https://github.com/moaxcp/x11/actions/workflows/gradle.yml/badge.svg)](https://github.com/moaxcp/x11/actions/workflows/gradle.yml)\n[![maven central](https://img.shields.io/maven-central/v/com.github.moaxcp.x11/x11-client)](https://search.maven.org/artifact/com.github.moaxcp.x11/x11-client)\n[![javadoc](https://javadoc.io/badge2/com.github.moaxcp.x11/x11-client/javadoc.svg)](https://javadoc.io/doc/com.github.moaxcp.x11/x11-client)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=moaxcp_x11-client\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=moaxcp_x11-client)\n\n# Users\n\nThe x11-client library can be added to your project using maven or gradle.\n\n## Maven\n\n```\n\u003cdependency\u003e\n \u003cgroupId\u003ecom.github.moaxcp.x11\u003c/groupId\u003e\n \u003cartifactId\u003ex11-client\u003c/artifactId\u003e\n \u003cversion\u003e0.22.0\u003c/version\u003e\n \u003ctype\u003emodule\u003c/type\u003e\n\u003c/dependency\u003e\n```\n\n## Gradle\n\n```\nimplementation 'com.github.moaxcp.x11:x11-client:0.22.0'\n```\n\n# Usage\n\nUsers build requests using the builder pattern.\n\n```\nCreateWindow window = CreateWindow.builder()\n        .depth(x11Client.getDepth(0))\n        .wid(x11Client.nextResourceId())\n        .parent(x11Client.getRoot(0))\n        .x((short) 10)\n        .y((short) 10)\n        .width((short) 600)\n        .height((short) 480)\n        .borderWidth((short) 5)\n        .clazz(COPY_FROM_PARENT)\n        .visual(x11Client.getVisualId(0))\n        .backgroundPixel(x11Client.getWhitePixel(0))\n        .borderPixel(x11Client.getBlackPixel(0))\n        .eventMaskEnable(EXPOSURE, KEY_PRESS)\n        .build();\n```\n\nAll protocol objects use the builder pattern. All fields using a value_mask \nwill automatically set the bit in the value_mask when the builder method is \ncalled. An example of this is shown above when eventMaskEnable is called.\n\n```\n...\n        .eventMaskEnable(EXPOSURE, KEY_PRESS)\n...\n```\n\nThis enables the value_mask bit for `eventMask` and turns on the `eventMask` \nbits for EXPOSURE and KEY_PRESS.\n\nA client is a resource and should be managed in a try-with-resources block. The \ntry-with-resources block will close the socket connection correctly.\n\n```\ntry(X11Client client = X11Client.connect(new DisplayName(\":1\"))) {\n\n}\n```\n\nIn this block requests can be sent through the client.\n\n```\nclient.send(window);\n```\n\nCreating a window is a one-way request. These requests do not receive a \nresponse from the server. Similar to X11lib, the client queues one-way requests \nuntil a two-way request is sent. This queue can be inspected and flushed to the \nserver.\n\n```\nclient.flush();\n```\n\nThis project converts the x11 protocol to classes which implement core\ninterfaces (XError, XEvent, XRequest, XReply, etc). The client can read and write these objects using the read and \nwrite methods defined in each object’s class.\n\nX11ProtocolExceptions may be thrown when there are IOExceptions with the socket. X11ClientExceptions are thrown with \nclient issues such as connection issues or api issues. X11ErrorExceptions represent \nErrors from the X11 Server. Errors can be handled using the standard try/catch \nmethod rather than using an error handler callback as is done with X11lib.\n\n```\ntry {\n  client.send(request);\n} catch(X11ErrorException e) {\n  LOG.error(e);\n}\n```\n\nAll supported x11 extensions are automatically loaded by the client on startup. \nUsers can check if an extension is loaded or activated by calling \n\n```\nclient.loadedPlugin(\"BIG-REQUESTS\");\nclient.activePlugin(\"BIG-REQUESTS\");\n```\n\nIf an extension is supported, then XRequests for that extension can be sent to \nthe client.\n\n```\nclient.send(Enable.builder().build());\n```\n\nOtherwise, sending an unsupported request will result in an exception.\n\n```\ncould not find plugin for request\n```\n\n# Examples\n\nThese examples are conversions of a X11lib example written in C.\n\n## Hello World\n\nThis is an example of a simple window. In this example none of the helper \nmethods are used. Raw requests are built and sent directly to the server.\n\n```\ntry(X11Client x11Client = X11Client.connect()) {\n  CreateWindow window = CreateWindow.builder()\n    .depth(x11Client.getDepth(0))\n    .wid(x11Client.nextResourceId())\n    .parent(x11Client.getRoot(0))\n    .x((short) 10)\n    .y((short) 10)\n    .width((short) 600)\n    .height((short) 480)\n    .borderWidth((short) 5)\n    .clazz(WindowClass.COPY_FROM_PARENT)\n    .visual(x11Client.getVisualId(0))\n    .backgroundPixel(x11Client.getWhitePixel(0))\n    .borderPixel(x11Client.getBlackPixel(0))\n    .eventMaskEnable(EventMask.EXPOSURE, EventMask.KEY_PRESS)\n    .build();\n  x11Client.send(window);\n  x11Client.send(MapWindow.builder()\n    .window(window.getWid())\n    .build());\n  CreateGC gc = CreateGC.builder()\n    .cid(x11Client.nextResourceId())\n    .drawable(window.getWid())\n    .background(x11Client.getWhitePixel(0))\n    .foreground(x11Client.getBlackPixel(0))\n    .build();\n  x11Client.send(gc);\n  while(true) {\n    XEvent event = x11Client.getNextEvent();\n    if(event instanceof ExposeEvent) {\n      List\u003cRectangle\u003e rectangles = new ArrayList\u003c\u003e();\n      rectangles.add(Rectangle.builder()\n        .x((short) 20)\n        .y((short) 20)\n        .width((short) 10)\n        .height((short) 10)\n        .build());\n      x11Client.send(PolyFillRectangle.builder()\n        .drawable(window.getWid())\n        .gc(gc.getCid())\n        .rectangles(rectangles)\n        .build());\n      x11Client.send(ImageText8.builder()\n        .drawable(window.getWid())\n        .gc(gc.getCid())\n        .string(stringToByteList(\"Hello World!\"))\n        .x((short) 10)\n        .y((short) 50)\n        .build());\n    } else if(event instanceof KeyPressEvent) {\n      break;\n    }\n  }\n}\n```\n\nThe next example is the same window but uses helper methods in the client.\n\n```\ntry(X11Client client = X11Client.connect()) {\n  int wid = client.createSimpleWindow((short) 10, (short) 10, (short) 600, (short) 480, EventMask.EXPOSURE, EventMask.KEY_PRESS);\n  client.storeName(wid, \"Hello World!\");\n  int deleteAtom = client.getAtom(\"WM_DELETE_WINDOW\");\n  client.setWMProtocols(wid, deleteAtom);\n  client.mapWindow(wid);\n  int gc = client.createGC(0, wid);\n  while(true) {\n    XEvent event = client.getNextEvent();\n    if(event instanceof ExposeEvent) {\n      client.fillRectangle(wid, gc, (short) 20, (short) 20, (short) 10, (short) 10);\n      client.drawString(wid, gc, (short) 10, (short) 50, \"Hello World!\");\n    } else if(event instanceof KeyPressEvent) {\n      break;\n    } else if(event instanceof ClientMessageEvent) {\n      ClientMessageEvent clientMessage = (ClientMessageEvent) event;\n      if(clientMessage.getFormat() == 32) {\n        ClientMessageData32 data = (ClientMessageData32) clientMessage.getData();\n        if(data.getData32().get(0) == deleteAtom) {\n          break;\n        }\n      }\n    }\n  }\n}\n```\n\n## TinyWM\n\n[TinyWM](http://incise.org/tinywm.html) is a famous small window manager \nwritten in around 50 lines of code. This example is the implementation in java.\n\n```\ntry(X11Client client = X11Client.connect(new DisplayName(\":1\"))) {\n  int wid = client.createSimpleWindow(10, 10, 200, 200);\n  client.mapWindow(wid);\n  client.send(GrabKey.builder()\n    .key((byte) client.keySymToKeyCode(KeySym.getByName(\"F1\").get().getValue()))\n    .modifiersEnable(ModMask.ONE)\n    .grabWindow(client.getRoot(0))\n    .ownerEvents(true)\n    .keyboardMode(GrabMode.ASYNC)\n    .pointerMode(GrabMode.ASYNC)\n    .build());\n  client.send(GrabButton.builder()\n    .button(ButtonIndex.ONE)\n    .modifiersEnable(ModMask.ONE)\n    .grabWindow(client.getRoot(0))\n    .ownerEvents(true)\n    .eventMaskEnable(BUTTON_PRESS, BUTTON_RELEASE, POINTER_MOTION)\n    .keyboardMode(GrabMode.ASYNC)\n    .pointerMode(GrabMode.ASYNC)\n    .build());\n  client.send(GrabButton.builder()\n    .button(ButtonIndex.THREE)\n    .modifiersEnable(ModMask.ONE)\n    .grabWindow(client.getRoot(0))\n    .ownerEvents(true)\n    .eventMaskEnable(BUTTON_PRESS, BUTTON_RELEASE, POINTER_MOTION)\n    .keyboardMode(GrabMode.ASYNC)\n    .pointerMode(GrabMode.ASYNC)\n    .build());\n\n  GetGeometryReply geometry = null;\n  ButtonPressEvent start = null;\n\n  while(true) {\n    XEvent event = client.getNextEvent();\n    if(event instanceof KeyPressEvent) {\n      KeyPressEvent keyPress = (KeyPressEvent) event;\n      int child = keyPress.getChild();\n      if(child != Window.NONE.getValue()) {\n        client.raiseWindow(child);\n      }\n    } else if(event instanceof ButtonPressEvent) {\n      ButtonPressEvent buttonPress = (ButtonPressEvent) event;\n      int child = buttonPress.getChild();\n      if(child != Window.NONE.getValue()) {\n        geometry = client.send(GetGeometry.builder()\n          .drawable(child)\n          .build());\n        start = buttonPress;\n      }\n    } else if(event instanceof MotionNotifyEvent) {\n      MotionNotifyEvent motionNotify = (MotionNotifyEvent) event;\n      int child = motionNotify.getChild();\n      if(child != Window.NONE.getValue()) {\n        int xdiff = motionNotify.getRootX() - start.getRootX();\n        int ydiff = motionNotify.getRootY() - start.getRootY();\n        client.send(ConfigureWindow.builder()\n          .window(child)\n          .x(geometry.getX() + (start.getDetail() == ButtonIndex.ONE.getValue() ? xdiff : 0))\n          .y(geometry.getY() + (start.getDetail() == ButtonIndex.ONE.getValue() ? ydiff : 0))\n          .width(Math.max(1, geometry.getWidth() + (start.getDetail() == ButtonIndex.THREE.getValue() ? xdiff : 0)))\n          .height(Math.max(1, geometry.getHeight() + (start.getDetail() == ButtonIndex.THREE.getValue() ? ydiff : 0)))\n          .build());\n      }\n    } else if(event instanceof ButtonReleaseEvent) {\n      start = null;\n    }\n  }\n}\n```\n\nThe java version is a bit longer due to the builder pattern being a little more\nverbose.\n\n# Design\n\n## Request Prossesing\n\nOneWayRequests are requests which the client expects no response from the \nserver. `OneWayRequests are queued and are only sent when the client is flushed. \nThere are 3 ways in which the client will be flushed.\n\n1. Manually by calling the `flush()` method\n2. sending a `TwoWayRequest`\n3. When the event queue is empty and `getNextEvent()` is called\n\nTwoWayRequests are requests where the client expects a response from the \nserver. These requests cause the client to flush the `OneWayRequest` queue and \nsend the `TwoWayRequest`. Next the client reads input from the server and \nattempts to find the corresponding `XReply` and return it. The protocol object \nread from the server can be a `XEvent` or `XError` rather than an `XReply`. The \nclient needs to handle these before it can find and return the `XReply`.When a \n`XEvent` is read it is stored in the event queue.\n\nWhen an `XError` is read it may be for the current request or any of the \nprevious OneWayRequests. Anytime an `XError` is found an exception will be \nthrown.\n\n## Error Handling\n\nNOTE: error handling per request has not been implemented. This could be in the\nform of providing an error handler when sending requests.\n\n## Event Prossesing\n\nEvents can be sent by the server at any time, so they are stored in an event \nqueue when processing TwoWayRequests. This allows the user to receive events by\ncalling `client.getNextEvent()`.\n\nThe event queue is an internal queue containing events which are deferred while \nprocessing a TwoWayRequest. `client.getNextEvent()` will empty this queue \nbefore reading events from the server. When the queue is empty getNextEvent() \nwill flush the `OneWayRequest` queue and attempt to find and return a `XEvent` \nfrom the server.\n\nWhen reading events from the server an error can be read. These errors can only \nbe a result of OneWayRequests that are sent after `flush()` is called. These\nerrors will be thrown as an exception.\n\nNote: Receiving an XReply while processing events should not be expected since \nsending TwoWayRequests clears the stream of replies.\n\n## Concurrency\n\nThe client is not thread safe and invocations from one thread must be isolated \nfrom invocations of another thread. The connection socket, one-way request \nqueue, and event queue are shared mutable data. All invocations must be \nsynchronized in some way. Protocol objects are immutable, which allows them to \nbe shared without synchronization.\n\n# Contributors\n\nSupport is most needed for example code. Other x11 libraries have tons of examples that prove the library works.\nSo far this project only has a few basic examples.\n\nI am not an x11 programmer but I find the protocol to be an interesting \nchallenge and learning experience. The only other x11 client implementation for \njava that I have found is escher. Escher is very hand written and has many \nissues. The goal of this client is to automate the generation of the protocol \nand make a clear distinction between the client and any framework that may \nprovide things like resource management and event dispatch.\n\nThis project uses the xcb xmls to generate protocol classes for the core \nprotocol and extensions. It uses a custom gradle plugin to generate the \nclasses. Be sure to check the javadoc to view supported protocol objects.\n\nAll protocol objects support read and write methods regardless of type. This \nmeans that these objects can also be used to build an x11 server and are not \ntied specifically to the client.\n\nXlib and XCB provides convenient methods rather than directly using the \nprotocol. I have avoided adding convenience methods to the client but may do \nso in the future. Methods such as createSimpleWindow can be added. If you have \nany suggestions on methods that can be added feel free to submit an issue or \nPR.\n\nThe core protocol and every supported extension implements a plugin which \nenables the client to figure out which class to use when reading errors and \nevents from the server. These plugins are generated durring the build process. \nPlugins are discovered and loaded using the ServiceLoader pattern.\n\n# Frameworks\n\nThere is a need for higher levels of abstraction such as Window, Pixmap, and \nGraphicsContext. As well as managing the creation and destruction of these \nobjects. There is also a need for dispatching events in a consistent way. These \nabstractions will be needed for any application and can be implemented in a \nframework. I would like to consider this the job of a Display class and \npossibly a Toolkit. Currently there is a Display class which manages Resources \nand event dispatch. A framework is not the primary goal of the client project \nand will likely move into a new project.\n\n# Other X11 Clients\n\nhttps://github.com/psychon/x11rb\n\nhttps://github.com/sidorares/node-x11\n\nhttps://github.com/BurntSushi/xgb\n\n# Learning x11\n\nhttps://cgit.freedesktop.org/xorg/proto/x11proto/plain/XF86keysym.h\n\nhttps://tronche.com/gui/x/xlib/input/keyboard-encoding.html\n\nhttps://jichu4n.com/posts/how-x-window-managers-work-and-how-to-write-one-part-i/\n\nhttps://www.geeks3d.com/20120102/programming-tutorial-simple-x11-x-window-code-sample-for-linux-and-mac-os-x/\n\nhttps://wiki.tcl-lang.org/page/Disable+autorepeat+under+X11\n\nhttps://p.janouch.name/article-xgb.html\n\nhttps://jamey.thesharps.us/2021/03/25/xcb-protocol-specifications-data/\n\nhttps://www.x.org/releases/X11R7.6/doc/libXtst/recordlib.html\n\n\n\n# versions\n\n## 0.22.0\n\n* switching to eclipse-collections\n\n## 0.21.0\n\n* Added support for no-sequence-number events which is only used in KeymapNotifyEvent\n    * This fixed part of the RecordApiExample\n* Fixed bug where generated code for reading generic events was missing from protocol plugins\n* Fixed bug in generated code for replies where reading pad align was missing\n* Adding XApi interfaces to cleanup client\n* Added examples and api to run examples\n* Fixed bug where new resource ids are not requested by the client when they run out\n\n## 0.20.0\n\nFixing XAuthority parsing following the format described [here](https://gitlab.freedesktop.org/xorg/lib/libxau/-/tree/master?ref_type=heads).\n\n## 0.19.0\n\n* Added support for little-endian and made it default to match the new server default (see \n[blog post](https://who-t.blogspot.com/2023/01/x-servers-no-longer-allow-byte-swapped.html)).\n\n## 0.18.2\n\n* Fixing XAuthority when parsing number\n* switched back to junixsocket as jdk does not support sockets only SocketChannel\n* Fixing usage of io.freefair.lombok in protocol projects. The module-path was not being set on the delombok task\n* fixing delombok by removing lombok from projects using junixsocket. Delombok does not support mutli-release jar files.\n* Switched back to junixsocket\n\n## 0.18.1\n\n* fixing delombok task so javadoc works again and the project can be published to maven central\n\n## 0.18.0\n\n* Switched to a multimodule project\n* Switched to jdk 21\n* Added java module system support\n* Removed delombok due to [issues](https://github.com/freefair/gradle-plugins/issues/824) with modules. This results in javadoc no longer being generated.\n* Removed dependency on junixsocket and switched to the jdk UnixDomainSocket.\n* Removed jbang\n* Moved all integration tests to the examples project with a main method.\n\n## 0.17.0\n\n* Adding generated protocol sources to git\n\n## 0.16.0\n\n* Renaming project to x11\n* Switching to a multiproject build.\n* Change integration tests into examples in example project.\n\n## 0.15.0\n\n* Adding RecordApi which provides a higher level api for reading records with parsed XObjects so the user does not need to parse the data.\n* Each XObject now has a static PLUGIN_NAME assigned to the plugin name and an instance getter method.\n* Plugins now use the header as the plugin name.\n* Added all plugin info from the xml file (extensionName, extensionXName, extensionMultiword)\n* added methods to client for reading protocol from any X11Input. This is used for reading data from the record extension and for testing read/write for any object.\n* Fixed issues with list lengths which need to be unsigned.\n\n## 0.14.0\n\n* Fixed issue where WILD XAuthority entries do not have an address\n* Fixed major bug when writing requests. For xproto the header should start with the OPCODE then 1 pad. For extensions the header should start with the majorOpcode then OPCODE. BigRequest and all QueryVersion requests worked because their OPCODE is 0 but everything else in extensions failed. This should be fixed for all extensions and has been tested with the RECORD extension.\n\n## 0.13.0\n\nProtocolPluginService now sets majorOpcode on XProtocolPlugins and uses it instead of majorVersion as the base opcode for requests. This fixes a bug in loading plugins and sending requests.\n\n## 0.12.0\n\nAdding jbang examples\nUpgrading dependencies\nRemoving rekon gradle plugin\n\n## 0.11.0\n\nAdding support for xkb except for GetKbdByName\n\n## 0.10.0\n\n[x] Made DeviceStateAbs_area and DeviceStateAbs_calib names DeviceStateAbsArea and DeviceStateAbsCalib\n[x] Adding other KeySyms from x11lib.\n\n## 0.9.0\n\n* Added support for resolving enums directly. In xinput.xml there is an Event `Property` which has the same name as the \nenum `Property` from xproto.xml. The current solution is to use `resolveXTypeEnum(String)` when resolving enums.\n\n* Added support for `\u003ceventstruct\u003e` tags.\n\n[x] plugin name constant is needed for checking the `\u003callowed\u003e` tag within `\u003ceventstruct\u003e`\n[x] offset is required to check if an event is supported by a specific `\u003ceventstruct\u003e`\n\n* Added support for readParams which are not part of the protocol for the object but passed in from another object's \nprotocol. This is needed for xinput `DeviceTimeCoord`.\n\n[x] Found bug with reading and writing events and errors for extensions. The offset must be subtracted from the number not \nadded.\n\n[x] Writing events is not possible without passing in the extension offset. The server will treat extension events like \nxproto events.\n\n[x] Added support for `\u003ccase\u003e` tags within a `\u003cswitch\u003e`. This creates an interface and implementing classes for each\ncase.\n\n## 0.8.0\n\nAdding support for glx and dri3 extensions\n\n## 0.7.0\n\n* Adding support for generic events\n* Adding support for the Present extension\n* Added ProtocolPluginService to handle plugins for the XProtocolService\n\n## 0.6.0\n\n* Implementing `sync()` method based on XSync but without a discard parameter.\n* Adding `discard()` method to clear the event queue. \n* Added `keyCodeToKeySym()` methods.\n* Added `keySymToKeyCodes()` method.\n* Added `getKeySym()` method.\n* `getAtom(int)` now returns an `AtomValue` which contains the id and name.\n* Added `getWMProtocols(int)` to returns the supported protocols for a window.\n* Added `killClient(int)` and `inputFocus(int)`.\n* Added Generator for KeySym enum.\n* Added KeyboardService to handle the keyboard for the client.\n* Added BasicWindowManager to example tests.\n\n## 0.5.0\n\nAdding `hasResponse()` method which checks for an available XEvent or XError on\nthe socket.\n\nSince DisplayName can set the default screen methods have been added to return\ndefault settings from the connection setup response.\n\n## 0.4.0\n\nRemoving length properties from protocol objects where it is simply the list\nsize. The length still needs to be set for properties involving complex\nexpressions. This results in not having to set the length of lists on most \nobjects. For example drawing a string no longer requires the size.\n\n```\nclient.send(ImageText8.builder()\n  .drawable(window.getWid())\n  .gc(gc.getCid())\n  .string(stringToByteList(\"Hello World!\"))\n  .x((short) 10)\n  .y((short) 50)\n  .build());\n```\n\nAdding exclude to x11protocol plugin.\n\nFixing issues with objects missing padding for the first field. This enables\nthe sync extension to work.\n\nAdded support for file descriptors. They are simply treated as an `int`.\n\nAdded extensions shm, sync xrandr, xv, and xvmc\n\nAdded defaultGC cache for root windows and method to automatically create them.\n\n## 0.3.0\n\nAdding TinyWM example.\n\nAdded keySymToKeyCode which can be used to grab keys.\n\nMoving XDisplay methods to main client. Removing XDisplay.\n\nMoved DisplayName, KeySym, KeySystem, ParametersCheck, and XAuthority to protocol package.\n\nAdding ResourceIdService which will switch to XC_MISC extension once ids run out.\n\nAdding AtomService which will cache InternAtoms.\n\n## 0.2.1\n\nAdding github actions build. The workflow will build the library and run a sonar scan.\n\nAdding keysymdef.h support for some of the keys.\n\n## 0.2.0\n\nFixed issue where the size of a padalign is returned as 0 rather than calculated.\n\nUpdating javadoc and adding tests. Refactoring classes for better package encapsulation.\n\n* Each plugin is now in its extension package\n* XProtocolService is in the client package and package private\n* Utilities, X11InputStream, and X11OutputStream is in the protocol package\n* Made ParametersCheck package private\n* ConnectionFailureException, X11ClientException, and X11ErrorException constructors are package private\n* X11ClientException is now used for IOExceptions thrown while connecting to the x11 server\n* X11Connection is now private\n\n## 0.1.0\n\nInitial release of x11-client. The client generates classes for bigreq, composite, damage, dpms, dri2, ge, record, res, \nscreensaver, shape, xc_misc, xevie, xf86dri, xf86vidmode, xfixes, xinerama, xproto, xselinux, and xtest.\n\n# License\n\nCopyright 2020 John Mercier\n\nPermission is hereby granted, free of charge, to any \nperson obtaining a copy of this software and \nassociated documentation files (the \"Software\"), to \ndeal in the Software without restriction, including \nwithout limitation the rights to use, copy, modify, \nmerge, publish, distribute, sublicense, and/or sell \ncopies of the Software, and to permit persons to \nwhom the Software is furnished to do so, subject to \nthe following conditions:\n\nThe above copyright notice and this permission notice \nshall be included in all copies or substantial \nportions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY \nOF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT \nLIMITED TO THE WARRANTIES OF MERCHANTABILITY, \nFITNESS FOR A PARTICULAR PURPOSE AND \nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR \nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES \nOR OTHER LIABILITY, WHETHER IN AN ACTION OF \nCONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR \nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \nDEALINGS IN THE SOFTWARE.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoaxcp%2Fx11","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoaxcp%2Fx11","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoaxcp%2Fx11/lists"}