Xtext: using the grammar classes in ISemanticHighlightingCalculator - syntax-highlighting

Listen, I have a grammar. See just the specific part I need to handle:
Par:
id=ID | string=STRING | integer=INT;
What I want to obtain is:
if it's a Par element of type ID then color the background
if it's a Par element of type STRING then set text color
And here is my SemanticHighlightingCalculator
public class GrailSemanticHighlightingCalculator implements ISemanticHighlightingCalculator {
#Override
public void provideHighlightingFor(XtextResource resource, IHighlightedPositionAcceptor acceptor) {
if (resource == null) return;
Iterable<AbstractNode> allNodes = NodeUtil.getAllContents( resource.getParseResult().getRootNode() );
for (AbstractNode node : allNodes) {
System.out.println(node.getGrammarElement().toString());
if (node.getGrammarElement() instanceof Par) {
System.out.println("Il mio par: " + ((Par)node).getId());
acceptor.addPosition(node.getOffset(), node.getLength(), GrailHighlightingConfiguration.ELEMENT_ID);
}
}
}
}
I'm doing this as written here in the documentation. I'm not getting any error at compile time. Here's an example output of System.out.println(node.getGrammarElement().toString());
org.eclipse.xtext.impl.RuleCallImpl#165a43b (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#159b3 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#a866a9 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl#f4c9c4 (cardinality: null) (value: ()
org.eclipse.xtext.impl.RuleCallImpl#a82a10 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#618b08 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl#1da2b6d (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl#591171 (cardinality: null) (value: ,)
org.eclipse.xtext.impl.RuleCallImpl#1882876 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#618b08 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl#1da2b6d (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl#591171 (cardinality: null) (value: ,)
org.eclipse.xtext.impl.RuleCallImpl#1882876 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#618b08 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl#1860e4 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl#ea8847 (cardinality: null) (value: ))
org.eclipse.xtext.impl.RuleCallImpl#812517 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#aa3e9a (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#f42d53 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#cbb612 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl#1990d96 (cardinality: null) (value: ()
org.eclipse.xtext.impl.RuleCallImpl#1e7f21 (cardinality: null)
org.eclipse.xtext.impl.ActionImpl#2c79a5 (cardinality: null) (feature: left, operator: =)
org.eclipse.xtext.impl.RuleCallImpl#aa3e9a (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#f42d53 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#cbb612 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl#1990d96 (cardinality: null) (value: ()
org.eclipse.xtext.impl.RuleCallImpl#1e7f21 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#aa3e9a (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#f42d53 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#cbb612 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#1e668c2 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl#1e7a4d0 (cardinality: null) (value: .)
org.eclipse.xtext.impl.RuleCallImpl#f55ff2 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl#16e3eb3 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#d67d61 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl#1860e4 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl#14afef4 (cardinality: null) (value: ))
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl#1c190a2 (cardinality: null) (value: AND)
org.eclipse.xtext.impl.RuleCallImpl#feba21 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl#16dd645 (cardinality: null) (value: NOT)
org.eclipse.xtext.impl.RuleCallImpl#e54f3 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl#1e668c2 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl#1e7a4d0 (cardinality: null) (value: .)
org.eclipse.xtext.impl.RuleCallImpl#f55ff2 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl#16e3eb3 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#d67d61 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl#eb3f66 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl#14afef4 (cardinality: null) (value: ))
org.eclipse.xtext.impl.RuleCallImpl#165a43b (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#159b3 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl#a866a9 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl#f4c9c4 (cardinality: null) (value: ()
org.eclipse.xtext.impl.RuleCallImpl#a82a10 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#618b08 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#1da2b6d (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl#ea8847 (cardinality: null) (value: ))
org.eclipse.xtext.impl.RuleCallImpl#812517 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#aa3e9a (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#f42d53 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#cbb612 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.KeywordImpl#1990d96 (cardinality: null) (value: ()
org.eclipse.xtext.impl.RuleCallImpl#1e7f21 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#aa3e9a (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#f42d53 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#cbb612 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl#1e668c2 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl#1e7a4d0 (cardinality: null) (value: .)
org.eclipse.xtext.impl.RuleCallImpl#f55ff2 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl#16e3eb3 (cardinality: null)
org.eclipse.xtext.impl.RuleCallImpl#d67d61 (cardinality: null)
org.eclipse.xtext.impl.TerminalRuleImpl#1eed0fb (name: WS)
org.eclipse.xtext.impl.RuleCallImpl#1860e4 (cardinality: null)
org.eclipse.xtext.impl.KeywordImpl#14afef4 (cardinality: null) (value: ))

I'm only just starting out with XText as well but I might be able to help. I was able to get syntax highlighting working for a small project with similar code to yours, but with a few differences. I found the useful forum posting on the Eclipse forums here.
Based on the console output it looks like it's never recognising any of the AbstractNodes as being an instance of Par.
The differences between the Eclipse forum and your code seem to be:
It uses Iterator<EObject> iter = EcoreUtil.getAllContents(resource, true); and a while loop to iterate through the results.
It checks the type (in your case for Par) against the EObject directly rather than using getGrammarElement.
It might be as simple as changing it as above, to something like:
public class GrailSemanticHighlightingCalculator implements ISemanticHighlightingCalculator {
#Override
public void provideHighlightingFor(XtextResource resource, IHighlightedPositionAcceptor acceptor) {
if (resource == null) return;
Iterator<EObject> iter = EcoreUtil.getAllContents(resource, true);
while (iter.hasNext()) {
EObject current = iter.next();
if (current instanceof Par) {
Par parNode = (Par) current;
if (parNode.getId() != null) {
acceptor.addPosition(node.getOffset(), node.getLength(), GrailHighlightingConfiguration.ELEMENT_ID);
} else if (parNode.getString() != null) {
acceptor.addPosition(node.getOffset(), node.getLength(), GrailHighlightingConfiguration.ELEMENT_STRING);
} else if (parNode.getInt() != null) {
acceptor.addPosition(node.getOffset(), node.getLength(), GrailHighlightingConfiguration.ELEMENT_INT);
}
}
}
}
I've included some code to handle the other highlighting options, so you'd need to add in the ELEMENT_STRING and ELEMENT_INT handlers to your configure() method in whatever your IHighlightingConfiguration class is called, to return the TextStyle applicable to them.
Also note that I have not tested any of the above, so it may actually be completely wrong and misleading! Hope it's not, though. :)

For Xtext 2.0, this code can be used as a template:
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.ui.editor.syntaxcoloring.IHighlightedPositionAcceptor;
import org.eclipse.xtext.ui.editor.syntaxcoloring.ISemanticHighlightingCalculator;
public class YourDslSemanticHighlightingCalculator implements ISemanticHighlightingCalculator {
#Override
public void provideHighlightingFor( XtextResource resource, IHighlightedPositionAcceptor acceptor ) {
if( resource == null ) {
return;
}
HighlightingSwitch switcher = new HighlightingSwitch( acceptor );
Iterator<EObject> iter = EcoreUtil.getAllContents(resource, true);
while(iter.hasNext()) {
EObject current = iter.next();
switcher.doSwitch( current );
}
}
private class HighlightingSwitch extends YourDslSwitch<Void> {
private final IHighlightedPositionAcceptor acceptor;
public HighlightingSwitch( IHighlightedPositionAcceptor acceptor ) {
this.acceptor = acceptor;
}
#Override
public Void caseOption( Option object ) {
INode node = getFirstFeatureNode( object, YourDslPackage.eINSTANCE.getOption_Name() );
highlightNode( node, YourDslHighlightingConfiguration.OPTION );
return null;
}
private void highlightNode( INode node, String id ) {
if( node == null )
return;
if( node instanceof ILeafNode ) {
acceptor.addPosition( node.getOffset(), node.getLength(), id );
} else {
for( ILeafNode leaf : node.getLeafNodes() ) {
if( !leaf.isHidden() ) {
acceptor.addPosition( leaf.getOffset(), leaf.getLength(), id );
}
}
}
}
}
public INode getFirstFeatureNode( EObject semantic, EStructuralFeature feature ) {
if( feature == null )
return NodeModelUtils.findActualNodeFor( semantic );
List<INode> nodes = NodeModelUtils.findNodesForFeature( semantic, feature );
if( !nodes.isEmpty() )
return nodes.get( 0 );
return null;
}
}
This iterates over all nodes in your model and invokes a case in the HighlightingSwitch.
In the case method, you need to locate the INode related to the feature or EObject instance that you care about and then, you can highlight it.
Note that getFirstFeatureNode() doesn't search the whole AST for a node; the implementation is actually pretty fast.
The style configuration looks like this:
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.xtext.ui.editor.syntaxcoloring.DefaultHighlightingConfiguration;
import org.eclipse.xtext.ui.editor.syntaxcoloring.IHighlightingConfigurationAcceptor;
import org.eclipse.xtext.ui.editor.utils.TextStyle;
public class YourDslHighlightingConfiguration extends DefaultHighlightingConfiguration {
public static final String OPTION = "yourDsl.option";
public void configure(IHighlightingConfigurationAcceptor acceptor) {
acceptor.acceptDefaultHighlighting( OPTION, "Option", option() );
super.configure( acceptor );
}
public TextStyle option() {
TextStyle textStyle = defaultTextStyle().copy();
textStyle.setColor( new RGB( 0, 26, 171 ) );
textStyle.setStyle( SWT.ITALIC );
return textStyle;
}
}
Don't forget to bind the two new classes in your UI module!

Related

Springboot components do not "reset" when I send a new request?

I have a Springboot application exposing a simple REST api, with several layers and autowired #Components, and I send a HTTP POST request to its #RestController through Postman, and in one of the subsequent components I'm doing stuff with the received data.
The problem is that when I send more requests in postman after the first has returned, the components seem to still contain information from the previous request that has already returned a response... How to avoid this? I want every request to be a "clean slate". It's almost as if it's not cleaning up when its done.. It's so annoying because I dont even know how to formulate the problem but I hope you understand.
In the following code the "actual_imported_rows" keeps increasing for subsequent requests:
#Data
#NoArgsConstructor
#Component
#Slf4j
public class StrekningImporter {
int expected_num_rows;
int actual_imported_rows;
HashMap<Long, StrekningEntity> successfulStrekning = new HashMap<>();
ArrayList<FailedImportEntry> unsuccessfulStrekning = new ArrayList<>();
public HashMap<Long, StrekningEntity> startImport(Sheet sheet, HashMap<Long, RegulativEntity> regulativHashMap,
HashMap<Long, SambandEntity> sambandHashMap) throws FailedImport {
expected_num_rows = sheet.getLastRowNum();
Iterator<Row> rows = sheet.iterator();
System.out.println("ACTUAL IMPORT SIZE: " + actual_imported_rows);
int rowNum = 0;
while (rows.hasNext()) {
// Skip header
if (rowNum == 0) {
rowNum++;
rows.next();
}
Row currentRow = rows.next();
try {
StrekningEntity strekning = iterateRow(currentRow, regulativHashMap, sambandHashMap);
successfulStrekning.put((long) strekning.getId(), strekning);
actual_imported_rows += 1;
} catch (FailedImportEntry failedImportEntry) {
unsuccessfulStrekning.add(failedImportEntry);
rowNum++;
continue;
}
rowNum++;
}
log.info("Imported Strekning : " + actual_imported_rows + " out of: " + expected_num_rows);
if (unsuccessfulStrekning.size() > 0) {
throw new FailedImport("Strekning", unsuccessfulStrekning);
}
return successfulStrekning;
}
private StrekningEntity iterateRow(Row currentRow, HashMap<Long, RegulativEntity> regulativHashMap,
HashMap<Long, SambandEntity> sambandHashMap) throws FailedImportEntry {
int strekning_id = 0;
String rutekode = "";
String vegkode = "";
int samband_id = 0;
String oppdragsgiver = "";
String fergeleie_fra = "";
String fergeleie_til = "";
double distanse = 0;
int reisetid = 0;
int regulativ_id = 0;
int sone = 0;
int sonepaslag = 0;
String vegnummer = "";
String merknad = "";
LocalDate gyldig_fra = null;
LocalDate gyldig_til = null;
StrekningEntity strekningEntity = null;
int colIndex = 0;
try {
int lastCellNum = currentRow.getLastCellNum();
for (; colIndex < lastCellNum; colIndex++) {
Cell currentCell = currentRow.getCell(colIndex);
switch (colIndex) {
case 0:
if (currentCell != null) {
strekning_id = (int) currentCell.getNumericCellValue();
}
break;
case 1:
if (currentCell != null) {
rutekode = currentCell.getStringCellValue();
}
break;
case 2:
if (currentCell != null) {
vegkode = currentCell.getStringCellValue();
}
break;
case 3:
if (currentCell != null) {
samband_id = (int) currentCell.getNumericCellValue();
}
break;
case 5:
if (currentCell != null) {
fergeleie_fra = currentCell.getStringCellValue();
}
break;
case 6:
if (currentCell != null) {
fergeleie_til = currentCell.getStringCellValue();
}
break;
case 8:
if (currentCell != null) {
break;
}
case 9:
if (currentCell != null) {
distanse = currentCell.getNumericCellValue();
}
break;
case 10:
if (currentCell != null) {
reisetid = (int) currentCell.getNumericCellValue();
}
break;
case 11:
if (currentCell != null) {
regulativ_id = (int) currentCell.getNumericCellValue();
}
break;
case 13:
if (currentCell != null) {
sone = (int) currentCell.getNumericCellValue();
}
break;
case 14:
if (currentCell != null) {
sonepaslag = (int) currentCell.getNumericCellValue();
}
break;
case 16:
if (currentCell != null) {
vegnummer = currentCell.getStringCellValue();
}
break;
case 17:
if (currentCell != null) {
merknad = currentCell.getStringCellValue();
}
break;
case 18:
if (currentCell != null) {
gyldig_fra = currentCell.getLocalDateTimeCellValue().toLocalDate();
}
break;
case 19:
if (currentCell != null) {
gyldig_til = currentCell.getLocalDateTimeCellValue().toLocalDate();
}
break;
default:
break;
}
}
SambandEntity samband = sambandHashMap.get((long) samband_id);
RegulativEntity regulativ = regulativHashMap.get((long) regulativ_id);
strekningEntity = new StrekningEntity((short) strekning_id, samband, fergeleie_fra, fergeleie_til,
(int) distanse, reisetid, regulativ, null, (short) sone, (short) sonepaslag, false, merknad, gyldig_fra,
gyldig_til, null);
} catch (Exception e) {
FailedImportEntry failedImportEntry = new FailedImportEntry(currentRow.getRowNum(), colIndex,
"class: " + e.getClass() + " | message: " + e.getMessage());
throw failedImportEntry;
}
return strekningEntity;
}
}
Any help or hints where the problem lies would be greatly appreciated :)

Why does it return null in my binary search tree, search method

I don't know why I am getting null in my method ?
public Node<E> search(int data, Node<E> start){
Node<E> foundNode = null;
if(data < start.getData()){
search(data, start.getLeftNode());
}
if(data > start.getData()){
search(data, start.getRightNode());
}
if(data == start.getData()){
foundNode = start;
}
return foundNode;
}
if I put System.out.println(foundNode); before the return statement I get the node but when it returns it I get null!!
You are missing the return statements for the recursive function calls:
search(data,start.getLeftNode()); and search(data, start.getRightNode());
Your method would only work when there are no recursive calls executed and if they are executed still foundNode that is returned remains NULL, since its a local variable.
So, correct code is:
public Node<E> search(int data, Node<E> start){
Node<E> foundNode = null;
if(data < start.getData()){
return search(data, start.getLeftNode());
}
if(data > start.getData()){
return search(data, start.getRightNode());
}
if(data == start.getData()){
foundNode = start;
}
return foundNode;
}
Here is my method:
private Node search(String name, Node node){
if(node != null){
if(node.name().equals(name)){
return node;
} else {
Node foundNode = search(name, node.left);
if(foundNode == null) {
foundNode = search(name, node.right);
}
return foundNode;
}
} else {
return null;
}
}

Find Ancestor method for binary search tree is not working

I had written the method for finding a node's parent in C# (c-sharp) but my code is not working correctly. Exceptions: System.NullReferenceException is thrown when I try to delete a node who's parent is null.
public TreeNode FindParent(int value, ref TreeNode parent)
{
TreeNode currentNode = root;
if (currentNode == null)
{
return null;
}
while (currentNode.value != value)
{
if (value < currentNode.value)
{
parent = currentNode;
currentNode = currentNode.leftChild;
}
if (value > currentNode.value)
{
parent = currentNode;
currentNode = currentNode.rightChild;
}
}
return currentNode;
}
public void Delete(int value)
{
TreeNode parent = null;
TreeNode nodeToDelete = FindParent(value, ref parent);
if (nodeToDelete == null)
{
throw new Exception("Unable to delete node: " + value.ToString());
}
//CASE 1: Nod has 0 children.
if (nodeToDelete.leftChild == null && nodeToDelete.rightChild == null)
{
if (parent.leftChild == nodeToDelete)
{
parent.leftChild = null;
}
if (parent.rightChild == nodeToDelete)
{
parent.rightChild = null;
}
count--;
return;
}
//CASE 2: Nod has 1 left || 1 right barn
if (nodeToDelete.leftChild == null && nodeToDelete.rightChild != null)
{
nodeToDelete.rightChild = parent.rightChild;
nodeToDelete = null;
count--;
return;
}
if (nodeToDelete.leftChild != null && nodeToDelete.rightChild == null)
{
nodeToDelete.leftChild = parent.leftChild;
nodeToDelete = null;
count--;
return;
}
//CASE 3: Nod has 2 children
if (nodeToDelete.rightChild != null && nodeToDelete.leftChild != null)
{
TreeNode successor = LeftMostNodeOnRight(nodeToDelete, ref parent);
TreeNode temp = new TreeNode(successor.value);
if (parent.leftChild == successor)
{
parent.leftChild = successor.rightChild;
}
else
{
parent.rightChild = successor.rightChild; nodeToDelete.value = temp.value;
}
count--;
return;
}
}
since you are using recursion , you don't need the parent Node to delete a node in a binary search tree, here is a delete method where you pass in int and the root
private BinaryTreeNode remove (int value, TreeNode t){
if(t==null)
return t; // not found; do nothing
if(value < t.value){
t.left = remove(x,y,t.left);
}
else if (value > t.value){
t.right = remove(x,y,t.right);
}
else if( t.left!=null && t.right != null) // two children
{
t.info = findMin(t.right).info;
remove(t.info.getLastName(),y,t.right);
}
else{ // one child
if (t.left != null) {
t = t.left;
}
else{
t = t.right;
}
}
return t;
}
Edit-----------findMin (find minimum node in a binary search tree)
private BinaryTreeNode findMin ( BinaryTreeNode t){ // recursive
if(t == null)
return null;
else if (t.left == null)
return t;
return findMin(t.left);
}
So you take the min value from the right subtree, and make it the parent of t.info. Follow these diagrams. We are deleting node 25 with two children.

how can I get information about the mouse, keyboard, gamepad in MAC OS

need information about the buttons of the device, how many, etc.
I tried iokit but got a strange list
name = IOUSBRootHubDevice
name = IOUSBHubDevice
name = IOUSBDevice
name = IOUSBHubDevice
name = IOUSBDevice
name = IOUSBRootHubDevice
name = IOUSBHubDevice
name = IOUSBDevice
name = IOUSBDevice
name = IOUSBDevice
my code
CFMutableDictionaryRef matchingDict;
io_iterator_t iter;
kern_return_t kr;
io_service_t device;
io_name_t name;
//io_object_t device;
/* set up a matching dictionary for the class */
matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
if (matchingDict == NULL){
return -1; // fail
}
/* Now we have a dictionary, get an iterator.*/
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr != KERN_SUCCESS){
return -1;
}
/* iterate */
while ((device = IOIteratorNext(iter))){
IOObjectGetClass(device, name);
printf("name = %s \n", name);
/* do something with device, eg. check properties */
/* ... */
/* And free the reference taken before continuing to the next item */
IOObjectRelease(device);
}
/* Done, release the iterator */
IOObjectRelease(iter);
there are probably a better option, but I can not find in google
turned himself in, as it so
static void MyCreateHIDDeviceInterface(io_object_t hidDevice,
IOHIDDeviceInterface122 ***hidDeviceInterface)
{
io_name_t className;
IOCFPlugInInterface **plugInInterface = NULL;
HRESULT plugInResult = S_OK;
SInt32 score = 0;
IOReturn ioReturnValue = kIOReturnSuccess;
ioReturnValue = IOObjectGetClass(hidDevice, className);
printf("Failed to get class name.\n");//print_errmsg_if_io_err(ioReturnValue, "Failed to get class name.");
printf("Found device type %s\n", className);
ioReturnValue = IOCreatePlugInInterfaceForService(hidDevice,
kIOHIDDeviceUserClientTypeID,
kIOCFPlugInInterfaceID,
&plugInInterface,
&score);
if (ioReturnValue == kIOReturnSuccess)
{
//Call a method of the intermediate plug-in to create the device
//interface
plugInResult = (*plugInInterface)->QueryInterface(plugInInterface,
CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),
(LPVOID *) hidDeviceInterface);
printf("Couldn't create HID class device interface.\n");//print_errmsg_if_err(plugInResult != S_OK, "Couldn't create HID class device interface");
IODestroyPlugInInterface(plugInInterface);
//(*plugInInterface)->Release(plugInInterface);
}
}
void getCookies(IOHIDDeviceInterface122** deviceInterface){
CFArrayRef elements;
CFDictionaryRef element;
CFTypeRef object;
long number;
long usagePage;
long usage;
IOHIDElementCookie cookie;
(*deviceInterface)->copyMatchingElements(deviceInterface, NULL, &elements);
for ( CFIndex i=0; i<CFArrayGetCount(elements); i++ ){
element = (CFDictionaryRef)CFArrayGetValueAtIndex(elements, i);
// Get usage page
object = CFDictionaryGetValue(element, CFSTR(kIOHIDElementUsagePageKey));
if( object==0 || CFGetTypeID(object) != CFNumberGetTypeID() ){
continue;
}
if( !CFNumberGetValue((CFNumberRef) object, kCFNumberLongType, &number) ){
continue;
}
usagePage = number;
if( usagePage!=kHIDPage_GenericDesktop && usagePage!=kHIDPage_Button ){
continue;
}
// Get usage
object = CFDictionaryGetValue( element, CFSTR(kIOHIDElementUsageKey) );
if( object==0 || CFGetTypeID(object) != CFNumberGetTypeID() ){
continue;
}
if( !CFNumberGetValue((CFNumberRef) object, kCFNumberLongType, &number) ){
continue;
}
usage = number;
// Get cookie
object = CFDictionaryGetValue( element, CFSTR(kIOHIDElementCookieKey) );
if( object==0 || CFGetTypeID(object) != CFNumberGetTypeID() ){
continue;
}
if( !CFNumberGetValue((CFNumberRef) object, kCFNumberLongType, &number) ){
continue;
}
cookie = (IOHIDElementCookie) number;
if(usagePage == kHIDPage_GenericDesktop){
switch( usage )
{
case kHIDUsage_GD_Pointer: {
printf("kHIDUsage_GD_Pointer \n");
break;
}
case kHIDUsage_GD_Mouse: {
printf("kHIDUsage_GD_Mouse \n");
break;
};
case kHIDUsage_GD_Joystick: {
printf("kHIDUsage_GD_Joystick \n");
break;
}
case kHIDUsage_GD_GamePad: {
printf("kHIDUsage_GD_GamePad \n");
break;
}
case kHIDUsage_GD_Keyboard:{
printf("kHIDUsage_GD_Keyboard \n");
break;
};
case kHIDUsage_GD_Keypad: {
printf("kHIDUsage_GD_Keypad \n");
break;
};
case kHIDUsage_GD_MultiAxisController:{
printf("kHIDUsage_GD_MultiAxisController \n");
break;
};
case kHIDUsage_GD_X: {
printf("kHIDUsage_GD_X \n");
break;
};
case kHIDUsage_GD_Y: {
printf("kHIDUsage_GD_Y \n");
break;
};
}
} else if( usagePage == kHIDPage_Button){
printf("kHIDPage_Button \n");
}
}
}
int main(int argc, const char * argv[])
{
CFMutableDictionaryRef matchingDict;
io_iterator_t iter;
kern_return_t kr;
io_object_t device;
char name[128];
IOHIDDeviceInterface122 **deviceInterface = NULL;
/* set up a matching dictionary for the class */
matchingDict = IOServiceMatching(kIOHIDDeviceKey);//kIOHIDDeviceKey
if (matchingDict == NULL)
{
return -1; // fail
}
/* Now we have a dictionary, get an iterator.*/
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, &iter);
if (kr != KERN_SUCCESS)
{
return -1;
}
/* iterate */
while ((device = IOIteratorNext(iter)))
{
IOObjectGetClass(device, name);
if(!strcmp(name,"BNBMouseDevice")){
MyCreateHIDDeviceInterface(device, &deviceInterface);
if(*deviceInterface != NULL){
getCookies(deviceInterface);
(*deviceInterface)->Release(deviceInterface);
}
printf("name = %s \n \n", name);
}else if(!strcmp(name,"AppleBluetoothHIDKeyboard")){
MyCreateHIDDeviceInterface(device, &deviceInterface);
if(*deviceInterface != NULL){
getCookies(deviceInterface);
(*deviceInterface)->Release(deviceInterface);
}
printf("name = %s \n \n", name);
}else if(!strcmp(name,"IOUSBHIDDriver")){
MyCreateHIDDeviceInterface(device, &deviceInterface);
if(*deviceInterface != NULL){
getCookies(deviceInterface);
(*deviceInterface)->Release(deviceInterface);
}
printf("name = %s \n \n", name);
}
IOObjectRelease(device);
}
/* Done, release the iterator */
IOObjectRelease(iter);
return 0;
}

Programmatically change Mac display brightness

How to change Mac display brightness from cocoa application?
CGDisplayIOServicePort is deprecated in OS 10.9 – so you have to use IOServiceGetMatchingServices to get the service parameter for IODisplaySetFloatParameter. Here's a basic function that looks for services named "display" and changes their brightness.
- (void) setBrightnessTo: (float) level
{
io_iterator_t iterator;
kern_return_t result = IOServiceGetMatchingServices(kIOMasterPortDefault,
IOServiceMatching("IODisplayConnect"),
&iterator);
// If we were successful
if (result == kIOReturnSuccess)
{
io_object_t service;
while ((service = IOIteratorNext(iterator))) {
IODisplaySetFloatParameter(service, kNilOptions, CFSTR(kIODisplayBrightnessKey), level);
// Let the object go
IOObjectRelease(service);
return;
}
}
}
And in Swift (via #Dov):
private func setBrightnessLevel(level: Float) {
var iterator: io_iterator_t = 0
let result = IOServiceGetMatchingServices(kIOMasterPortDefault,
IOServiceMatching("IODisplayConnect").takeUnretainedValue(),
&iterator)
if result == kIOReturnSuccess {
var service: io_object_t = 1
for ;; {
service = IOIteratorNext(iterator)
if service == 0 {
break
}
IODisplaySetFloatParameter(service, 0, kIODisplayBrightnessKey, level)
IOObjectRelease(service)
}
}
}
(code is open source of course)
Expanding on Alex's answer:
In Xcode8 beta3 with Swift3, the code is a lot more streamlined.
private func setBrightness(level: Float) {
let service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IODisplayConnect"))
IODisplaySetFloatParameter(service, 0, kIODisplayBrightnessKey, level)
IOObjectRelease(service)
}
From Alec Jacobson's Brightness Menu source code:
- (void) set_brightness:(float) new_brightness {
CGDirectDisplayID display[kMaxDisplays];
CGDisplayCount numDisplays;
CGDisplayErr err;
err = CGGetActiveDisplayList(kMaxDisplays, display, &numDisplays);
if (err != CGDisplayNoErr)
printf("cannot get list of displays (error %d)\n",err);
for (CGDisplayCount i = 0; i < numDisplays; ++i) {
CGDirectDisplayID dspy = display[i];
CFDictionaryRef originalMode = CGDisplayCurrentMode(dspy);
if (originalMode == NULL)
continue;
io_service_t service = CGDisplayIOServicePort(dspy);
float brightness;
err= IODisplayGetFloatParameter(service, kNilOptions, kDisplayBrightness,
&brightness);
if (err != kIOReturnSuccess) {
fprintf(stderr,
"failed to get brightness of display 0x%x (error %d)",
(unsigned int)dspy, err);
continue;
}
err = IODisplaySetFloatParameter(service, kNilOptions, kDisplayBrightness,
new_brightness);
if (err != kIOReturnSuccess) {
fprintf(stderr,
"Failed to set brightness of display 0x%x (error %d)",
(unsigned int)dspy, err);
continue;
}
}
}
in Xcode 8 beta 6 does not compile:
IODisplaySetFloatParameter(service, 0, kIODisplayBrightnessKey, level)
Cannot convert value of type 'String' to expected argument type 'CFString!'
so let' cast it:
IODisplaySetFloatParameter(service, 0, kIODisplayBrightnessKey as CFString!, level)

Resources