{"id":7378,"date":"2026-02-07T00:01:50","date_gmt":"2026-02-07T08:01:50","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=7378"},"modified":"2026-02-14T11:21:24","modified_gmt":"2026-02-14T19:21:24","slug":"what-is-the-mouse-doing","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=7378","title":{"rendered":"What is the Mouse Doing?"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-300x167.jpg\" alt=\"\" width=\"300\" height=\"167\" class=\"alignnone size-medium wp-image-7374\" srcset=\"https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-300x167.jpg 300w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-1024x569.jpg 1024w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-768x427.jpg 768w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-1536x853.jpg 1536w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701-500x278.jpg 500w, https:\/\/c-for-dummies.com\/blog\/wp-content\/uploads\/2026\/01\/House-mouse-Mus-musculus-shutterstock_321795701.jpg 2000w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><br \/>\nContinuing from <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7363\">last week&#8217;s Lesson<\/a>, once activated and configured, the output that mouse activity generates in a terminal window looks something like this:<br \/>\n<!--more--><\/p>\n<pre>^[[<35;49;15M^[[<35;49;16M^[[<35;49;17M^[[<35;48;17M^[[<35;48;16M^[[<35;47;16M^[[<35;47;17M^[[<35;47;16M^[[<35;46;16M^[[<0;46;16M^[[<0;46;16m<\/pre>\n<p>This data follows a predictable pattern, which helps a mouse-happy program to read mouse input:<\/p>\n<ul>\n<li><code>^[<\/code> (\\e) the escape character<\/li>\n<li><code>[<\/code> left bracket<\/li>\n<li><code>&lt;<\/code> less than character<\/li>\n<li><code><em>nn<\/em><\/code> mouse button data<\/li>\n<li><code>;<\/code> semicolon separator<\/li>\n<li><code><em>nn<\/em><\/code> column (x) position<\/li>\n<li><code>;<\/code> semicolon separator<\/li>\n<li><code><em>nn<\/em><\/code> row (y) position<\/li>\n<li><code>M<\/code> or <code>m<\/code>, where <code>M<\/code> is for movement or button press and <code>m<\/code> is for button release<\/li>\n<\/ul>\n<p>For the mouse position, the upper left corner of the screen is location 1, 1. Values increase across to the right and vertically down, with the final value based on the screen size. For example:<\/p>\n<p><code>^[[&lt;35;49;15M<\/code><\/p>\n<p>This data tidbit shows that the mouse is moving (or no button is pressed) and is currently at column 49, row 15.<\/p>\n<p><code>^[[&lt;0;46;16M^[[&lt;0;46;16m<\/code><\/p>\n<p>This pair shows mouse button zero (the left button) is clicked at column 46, row 16 and released at the same character position. Here are the mouse button values:<\/p>\n<table width=\"450\">\n<tr>\n<td align=\"center\" width=\"75\"><strong>Value<\/strong><\/td>\n<td><strong>Button<\/strong><\/td>\n<\/th>\n<tr>\n<td align=\"center\" width=\"75\">0<\/td>\n<td>Left<\/td>\n<\/tr>\n<tr>\n<td align=\"center\" width=\"75\">1<\/td>\n<td>Middle<\/td>\n<\/tr>\n<tr>\n<td align=\"center\" width=\"75\">2<\/td>\n<td>Right<\/td>\n<\/tr>\n<tr>\n<td align=\"center\" width=\"75\">35<\/td>\n<td>(Movement)<\/td>\n<\/tr>\n<tr>\n<td align=\"center\" width=\"75\">64<\/td>\n<td>Scroll up<\/td>\n<\/tr>\n<tr>\n<td align=\"center\" width=\"75\">65<\/td>\n<td>Scroll down<\/td>\n<\/tr>\n<tr>\n<td align=\"center\" width=\"75\">+4<\/td>\n<td>Shift key pressed<\/td>\n<\/tr>\n<tr>\n<td align=\"center\" width=\"75\">+8<\/td>\n<td>Alt key pressed<\/td>\n<\/tr>\n<tr>\n<td align=\"center\" width=\"75\">+16<\/td>\n<td>Ctrl key pressed<\/td>\n<\/tr>\n<\/table>\n<p>The following code configures the terminal window to read the mouse and generate output reporting the mouse's position and clicks as documented above:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2026_02_07-Lesson-a.c\" rel=\"noopener\" target=\"_blank\">2026_02_07-Lesson-a.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;unistd.h&gt;\r\n\r\n#define mouse_enable() printf(\"\\e[?1000h\")\r\n#define mouse_extended() printf(\"\\e[?1006h\")\r\n#define mouse_disable() printf(\"\\e[?1000l\")\r\n\r\nint main()\r\n{\r\n    char buffer[12];\r\n    int key;\r\n\r\n    <span class=\"comments\">\/* enable mouse reporting *\/<\/span>\r\n    mouse_enable();\r\n    mouse_extended();\r\n    <span class=\"comments\">\/* remove line buffering *\/<\/span>\r\n    setvbuf(stdin,NULL,_IONBF,0);\r\n\r\n    <span class=\"comments\">\/* read stdin *\/<\/span>\r\n    puts(\"Click the mouse; press Enter to end\");\r\n    while( (key=getchar()) != '\\n' )\r\n    {\r\n        read(fileno(stdin),buffer,12);\r\n        write(fileno(stdout),buffer,12);\r\n    }\r\n\r\n    <span class=\"comments\">\/* clean-up *\/<\/span>\r\n    mouse_disable();    <span class=\"comments\">\/* disable mouse reporting *\/<\/span>\r\n    return 0;\r\n}<\/pre>\n<p>This code activates the mouse and turns on extended monitoring, which ensures that the output is something that a human can read. It also calls the <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=3701\"><em>setvbuf()<\/em> function<\/a> to disable input buffering. Normally this function is used on <em>stdout<\/em>, but keep in mind that the mouse data is reported by standard input. This aspect of reading mouse data is weird, plus it creates some interesting problems that I cover later.<\/p>\n<p>The main part of the program is a <em>while<\/em> loop that uses the <em>read()<\/em> function to obtain standard input in 12-character chunks. This information is then written to standard output. The loop continues until the Enter key is pressed.<\/p>\n<p>Before the program quits, the <em>mouse_disable()<\/em> macro is called. If you accidentally quit the program (press Ctrl+C), remember to use the <em>reset<\/em> command in the terminal window to stop mouse reporting from overwhelming the screen.<\/p>\n<p>Here's a sample run:<\/p>\n<pre>Click the mouse; press Enter to end\r\n^[[<0;1;1M^[[<0;1;1m^[[<0;1;1M^[[<0;1;1m^[[<0;11;2M^[[<0;11;2m\r\n[<0;1;1M\r\n2M<\/pre>\n<p>The garbage you see on the last two lines of output consists of leftover characters flowing from somewhere. You may need to press Enter a few times to end the program, which is why the following update provides better mouse monitoring:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2026_02_07-Lesson-b.c\" rel=\"noopener\" target=\"_blank\">2026_02_07-Lesson-b.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;termios.h&gt;\r\n#include &lt;unistd.h&gt;\r\n\r\n#define mouse_enable() printf(\"\\e[?1000h\")\r\n#define mouse_extended() printf(\"\\e[?1006h\")\r\n#define mouse_disable() printf(\"\\e[?1000l\")\r\n\r\nint main()\r\n{\r\n    struct termios original,noecho;\r\n    char buffer[12];\r\n    int key;\r\n\r\n    <span class=\"comments\">\/* obtain terminal configuration *\/<\/span>\r\n    tcgetattr(fileno(stdin),&amp;original);\r\n    noecho = original;        <span class=\"comments\">\/* duplicate *\/<\/span>\r\n        <span class=\"comments\">\/* enable raw input *\/<\/span>\r\n    noecho.c_lflag = noecho.c_lflag ^ ICANON;\r\n        <span class=\"comments\">\/* disable full duplex *\/<\/span>\r\n    noecho.c_lflag = noecho.c_lflag ^ ECHO;\r\n        <span class=\"comments\">\/* update terminal definition *\/<\/span>\r\n    tcsetattr(fileno(stdin), TCSANOW, &amp;noecho);\r\n\r\n    <span class=\"comments\">\/* enable mouse reporting *\/<\/span>\r\n    mouse_enable();\r\n    mouse_extended();\r\n    <span class=\"comments\">\/* remove line buffering *\/<\/span>\r\n    setvbuf(stdin,NULL,_IONBF,0);\r\n\r\n    <span class=\"comments\">\/* read stdin *\/<\/span>\r\n    puts(\"Click the mouse; press Enter to end\");\r\n    while( (key=getchar()) != '\\n' )\r\n    {\r\n        read(fileno(stdin),buffer,12);\r\n        write(fileno(stdout),buffer,12);\r\n        putchar('\\n');\r\n    }\r\n\r\n    <span class=\"comments\">\/* clean-up *\/<\/span>\r\n    mouse_disable();    <span class=\"comments\">\/* disable mouse reporting *\/<\/span>\r\n    tcsetattr(fileno(stdin), TCSANOW, &amp;original);\r\n    return 0;\r\n}<\/pre>\n<p>The primary update to this version of the code is adding terminal control via <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7339\">the <em>tcsetattr()<\/em> function<\/a>. Raw data input is enabled and duplex output (local echo) is disabled. I also added a newline output in the <em>while<\/em> loop, which presents the mouse data vertically.<\/p>\n<p>The program runs the same, with the output is presented in a single column:<\/p>\n<pre>Click the mouse; press Enter to end\r\n[<0;64;21M\r\n[<0;64;21m\r\n[<0;58;21M\r\n[<0;58;21m\r\n[<0;31;11M\r\n[<0;31;11m\r\n[<0;1;1M1m\r\n[<0;1;1m1m<\/pre>\n<p>This program reads the mouse data, but only clicks. In <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7397\">next week's Lesson<\/a>, I update the code with the ANSI command to monitor mouse movement.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The mouse-reading code can be updated to better read the input, which requires careful terminal manipulation. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7378\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-7378","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7378","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7378"}],"version-history":[{"count":16,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7378\/revisions"}],"predecessor-version":[{"id":7415,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7378\/revisions\/7415"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7378"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7378"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7378"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}