text:
var searchData=
[
  ['glfwcreatecursor',['glfwCreateCursor',['../group__input.html#gafca356935e10135016aa49ffa464c355',1,'glfw3.h']]],
  ['glfwcreatestandardcursor',['glfwCreateStandardCursor',['../group__input.html#gaa65f416d03ebbbb5b8db71a489fcb894',1,'glfw3.h']]],
  ['glfwcreatewindow',['glfwCreateWindow',['../group__window.html#ga5c336fddf2cbb5b92f65f10fb6043344',1,'glfw3.h']]],
  ['glfwcreatewindowsurface',['glfwCreateWindowSurface',['../group__vulkan.html#ga1a24536bec3f80b08ead18e28e6ae965',1,'glfw3.h']]],
  ['glfwdefaultwindowhints',['glfwDefaultWindowHints',['../group__window.html#gaa77c4898dfb83344a6b4f76aa16b9a4a',1,'glfw3.h']]],
  ['glfwdestroycursor',['glfwDestroyCursor',['../group__input.html#ga81b952cd1764274d0db7fb3c5a79ba6a',1,'glfw3.h']]],
  ['glfwdestroywindow',['glfwDestroyWindow',['../group__window.html#gacdf43e51376051d2c091662e9fe3d7b2',1,'glfw3.h']]],
  ['glfwextensionsupported',['glfwExtensionSupported',['../group__context.html#ga87425065c011cef1ebd6aac75e059dfa',1,'glfw3.h']]],
  ['glfwfocuswindow',['glfwFocusWindow',['../group__window.html#ga873780357abd3f3a081d71a40aae45a1',1,'glfw3.h']]],
  ['glfwgetclipboardstring',['glfwGetClipboardString',['../group__input.html#ga5aba1d704d9ab539282b1fbe9f18bb94',1,'glfw3.h']]],
  ['glfwgetcocoamonitor',['glfwGetCocoaMonitor',['../group__native.html#gaf22f429aec4b1aab316142d66d9be3e6',1,'glfw3native.h']]],
  ['glfwgetcocoawindow',['glfwGetCocoaWindow',['../group__native.html#gac3ed9d495d0c2bb9652de5a50c648715',1,'glfw3native.h']]],
  ['glfwgetcurrentcontext',['glfwGetCurrentContext',['../group__context.html#gac84759b1f6c2d271a4fea8ae89ec980d',1,'glfw3.h']]],
  ['glfwgetcursorpos',['glfwGetCursorPos',['../group__input.html#ga01d37b6c40133676b9cea60ca1d7c0cc',1,'glfw3.h']]],
  ['glfwgeteglcontext',['glfwGetEGLContext',['../group__native.html#ga671c5072becd085f4ab5771a9c8efcf1',1,'glfw3native.h']]],
  ['glfwgetegldisplay',['glfwGetEGLDisplay',['../group__native.html#ga1cd8d973f47aacb5532d368147cc3138',1,'glfw3native.h']]],
  ['glfwgeteglsurface',['glfwGetEGLSurface',['../group__native.html#ga2199b36117a6a695fec8441d8052eee6',1,'glfw3native.h']]],
  ['glfwgetframebuffersize',['glfwGetFramebufferSize',['../group__window.html#ga0e2637a4161afb283f5300c7f94785c9',1,'glfw3.h']]],
  ['glfwgetgammaramp',['glfwGetGammaRamp',['../group__monitor.html#gab7c41deb2219bde3e1eb756ddaa9ec80',1,'glfw3.h']]],
  ['glfwgetglxcontext',['glfwGetGLXContext',['../group__native.html#ga62d884114b0abfcdc2930e89f20867e2',1,'glfw3native.h']]],
  ['glfwgetglxwindow',['glfwGetGLXWindow',['../group__native.html#ga1ed27b8766e859a21381e8f8ce18d049',1,'glfw3native.h']]],
  ['glfwgetinputmode',['glfwGetInputMode',['../group__input.html#gaf5b859dbe19bdf434e42695ea45cc5f4',1,'glfw3.h']]],
  ['glfwgetinstanceprocaddress',['glfwGetInstanceProcAddress',['../group__vulkan.html#gadf228fac94c5fd8f12423ec9af9ff1e9',1,'glfw3.h']]],
  ['glfwgetjoystickaxes',['glfwGetJoystickAxes',['../group__input.html#ga6271d46a5901ec2c99601ccf4dd14731',1,'glfw3.h']]],
  ['glfwgetjoystickbuttons',['glfwGetJoystickButtons',['../group__input.html#gace54cd930dcd502e118fe4021384ce1b',1,'glfw3.h']]],
  ['glfwgetjoystickname',['glfwGetJoystickName',['../group__input.html#gac8d7f6107e05cfd106cfba973ab51e19',1,'glfw3.h']]],
  ['glfwgetkey',['glfwGetKey',['../group__input.html#gadd341da06bc8d418b4dc3a3518af9ad2',1,'glfw3.h']]],
  ['glfwgetkeyname',['glfwGetKeyName',['../group__input.html#ga237a182e5ec0b21ce64543f3b5e7e2be',1,'glfw3.h']]],
  ['glfwgetmirdisplay',['glfwGetMirDisplay',['../group__native.html#ga40dd05325d9813fa67d61328c51d2930',1,'glfw3native.h']]],
  ['glfwgetmirmonitor',['glfwGetMirMonitor',['../group__native.html#gae0941c11dc8f01aeb7cbb563f5cd930b',1,'glfw3native.h']]],
  ['glfwgetmirwindow',['glfwGetMirWindow',['../group__native.html#ga964d52bb7932216c379762eef1ea9b05',1,'glfw3native.h']]],
  ['glfwgetmonitorname',['glfwGetMonitorName',['../group__monitor.html#ga79a34ee22ff080ca954a9663e4679daf',1,'glfw3.h']]],
  ['glfwgetmonitorphysicalsize',['glfwGetMonitorPhysicalSize',['../group__monitor.html#ga7d8bffc6c55539286a6bd20d32a8d7ea',1,'glfw3.h']]],
  ['glfwgetmonitorpos',['glfwGetMonitorPos',['../group__monitor.html#ga102f54e7acc9149edbcf0997152df8c9',1,'glfw3.h']]],
  ['glfwgetmonitors',['glfwGetMonitors',['../group__monitor.html#ga3fba51c8bd36491d4712aa5bd074a537',1,'glfw3.h']]],
  ['glfwgetmousebutton',['glfwGetMouseButton',['../group__input.html#gac1473feacb5996c01a7a5a33b5066704',1,'glfw3.h']]],
  ['glfwgetnsglcontext',['glfwGetNSGLContext',['../group__native.html#ga559e002e3cd63c979881770cd4dc63bc',1,'glfw3native.h']]],
  ['glfwgetphysicaldevicepresentationsupport',['glfwGetPhysicalDevicePresentationSupport',['../group__vulkan.html#gaff3823355cdd7e2f3f9f4d9ea9518d92',1,'glfw3.h']]],
  ['glfwgetprimarymonitor',['glfwGetPrimaryMonitor',['../group__monitor.html#ga721867d84c6d18d6790d64d2847ca0b1',1,'glfw3.h']]],
  ['glfwgetprocaddress',['glfwGetProcAddress',['../group__context.html#ga35f1837e6f666781842483937612f163',1,'glfw3.h']]],
  ['glfwgetrequiredinstanceextensions',['glfwGetRequiredInstanceExtensions',['../group__vulkan.html#ga1abcbe61033958f22f63ef82008874b1',1,'glfw3.h']]],
  ['glfwgettime',['glfwGetTime',['../group__input.html#gaa6cf4e7a77158a3b8fd00328b1720a4a',1,'glfw3.h']]],
  ['glfwgettimerfrequency',['glfwGetTimerFrequency',['../group__input.html#ga3289ee876572f6e91f06df3a24824443',1,'glfw3.h']]],
  ['glfwgettimervalue',['glfwGetTimerValue',['../group__input.html#ga09b2bd37d328e0b9456c7ec575cc26aa',1,'glfw3.h']]],
  ['glfwgetversion',['glfwGetVersion',['../group__init.html#ga9f8ffaacf3c269cc48eafbf8b9b71197',1,'glfw3.h']]],
  ['glfwgetversionstring',['glfwGetVersionString',['../group__init.html#ga23d47dc013fce2bf58036da66079a657',1,'glfw3.h']]],
  ['glfwgetvideomode',['glfwGetVideoMode',['../group__monitor.html#gafc1bb972a921ad5b3bd5d63a95fc2d52',1,'glfw3.h']]],
  ['glfwgetvideomodes',['glfwGetVideoModes',['../group__monitor.html#ga820b0ce9a5237d645ea7cbb4bd383458',1,'glfw3.h']]],
  ['glfwgetwaylanddisplay',['glfwGetWaylandDisplay',['../group__native.html#gaaf8118a3c877f3a6bc8e7a649519de5e',1,'glfw3native.h']]],
  ['glfwgetwaylandmonitor',['glfwGetWaylandMonitor',['../group__native.html#gab10427a667b6cd91eec7709f7a906bd3',1,'glfw3native.h']]],
  ['glfwgetwaylandwindow',['glfwGetWaylandWindow',['../group__native.html#ga4738d7aca4191363519a9a641c3ab64c',1,'glfw3native.h']]],
  ['glfwgetwglcontext',['glfwGetWGLContext',['../group__native.html#gadc4010d91d9cc1134d040eeb1202a143',1,'glfw3native.h']]],
  ['glfwgetwin32adapter',['glfwGetWin32Adapter',['../group__native.html#gac84f63a3f9db145b9435e5e0dbc4183d',1,'glfw3native.h']]],
  ['glfwgetwin32monitor',['glfwGetWin32Monitor',['../group__native.html#gac408b09a330749402d5d1fa1f5894dd9',1,'glfw3native.h']]],
  ['glfwgetwin32window',['glfwGetWin32Window',['../group__native.html#gafe5079aa79038b0079fc09d5f0a8e667',1,'glfw3native.h']]],
  ['glfwgetwindowattrib',['glfwGetWindowAttrib',['../group__window.html#gacccb29947ea4b16860ebef42c2cb9337',1,'glfw3.h']]],
  ['glfwgetwindowframesize',['glfwGetWindowFrameSize',['../group__window.html#ga1a9fd382058c53101b21cf211898f1f1',1,'glfw3.h']]],
  ['glfwgetwindowmonitor',['glfwGetWindowMonitor',['../group__window.html#gaeac25e64789974ccbe0811766bd91a16',1,'glfw3.h']]],
  ['glfwgetwindowpos',['glfwGetWindowPos',['../group__window.html#ga73cb526c000876fd8ddf571570fdb634',1,'glfw3.h']]],
  ['glfwgetwindowsize',['glfwGetWindowSize',['../group__window.html#gaeea7cbc03373a41fb51cfbf9f2a5d4c6',1,'glfw3.h']]],
  ['glfwgetwindowuserpointer',['glfwGetWindowUserPointer',['../group__window.html#ga17807ce0f45ac3f8bb50d6dcc59a4e06',1,'glfw3.h']]],
  ['glfwgetx11adapter',['glfwGetX11Adapter',['../group__native.html#ga088fbfa80f50569402b41be71ad66e40',1,'glfw3native.h']]],
  ['glfwgetx11display',['glfwGetX11Display',['../group__native.html#ga8519b66594ea3ef6eeafaa2e3ee37406',1,'glfw3native.h']]],
  ['glfwgetx11monitor',['glfwGetX11Monitor',['../group__native.html#gab2f8cc043905e9fa9b12bfdbbcfe874c',1,'glfw3native.h']]],
  ['glfwgetx11window',['glfwGetX11Window',['../group__native.html#ga90ca676322740842db446999a1b1f21d',1,'glfw3native.h']]],
  ['glfwhidewindow',['glfwHideWindow',['../group__window.html#ga49401f82a1ba5f15db5590728314d47c',1,'glfw3.h']]],
  ['glfwiconifywindow',['glfwIconifyWindow',['../group__window.html#ga1bb559c0ebaad63c5c05ad2a066779c4',1,'glfw3.h']]],
  ['glfwinit',['glfwInit',['../group__init.html#ga317aac130a235ab08c6db0834907d85e',1,'glfw3.h']]],
  ['glfwjoystickpresent',['glfwJoystickPresent',['../group__input.html#gaffcbd9ac8ee737fcdd25475123a3c790',1,'glfw3.h']]],
  ['glfwmakecontextcurrent',['glfwMakeContextCurrent',['../group__context.html#ga1c04dc242268f827290fe40aa1c91157',1,'glfw3.h']]],
  ['glfwmaximizewindow',['glfwMaximizeWindow',['../group__window.html#ga3f541387449d911274324ae7f17ec56b',1,'glfw3.h']]],
  ['glfwpollevents',['glfwPollEvents',['../group__window.html#ga37bd57223967b4211d60ca1a0bf3c832',1,'glfw3.h']]],
  ['glfwpostemptyevent',['glfwPostEmptyEvent',['../group__window.html#gab5997a25187e9fd5c6f2ecbbc8dfd7e9',1,'glfw3.h']]],
  ['glfwrestorewindow',['glfwRestoreWindow',['../group__window.html#ga52527a5904b47d802b6b4bb519cdebc7',1,'glfw3.h']]],
  ['glfwsetcharcallback',['glfwSetCharCallback',['../group__input.html#ga556239421c6a5a243c66fca28da9f742',1,'glfw3.h']]],
  ['glfwsetcharmodscallback',['glfwSetCharModsCallback',['../group__input.html#ga3f55ef5dc03a374e567f068b13c94afc',1,'glfw3.h']]],
  ['glfwsetclipboardstring',['glfwSetClipboardString',['../group__input.html#gaba1f022c5eb07dfac421df34cdcd31dd',1,'glfw3.h']]],
  ['glfwsetcursor',['glfwSetCursor',['../group__input.html#gad3b4f38c8d5dae036bc8fa959e18343e',1,'glfw3.h']]],
  ['glfwsetcursorentercallback',['glfwSetCursorEnterCallback',['../group__input.html#gaa299c41dd0a3d171d166354e01279e04',1,'glfw3.h']]],
  ['glfwsetcursorpos',['glfwSetCursorPos',['../group__input.html#ga04b03af936d906ca123c8f4ee08b39e7',1,'glfw3.h']]],
  ['glfwsetcursorposcallback',['glfwSetCursorPosCallback',['../group__input.html#ga7dad39486f2c7591af7fb25134a2501d',1,'glfw3.h']]],
  ['glfwsetdropcallback',['glfwSetDropCallback',['../group__input.html#ga41291bf15dd3ff564b3143aa6dc74a4b',1,'glfw3.h']]],
  ['glfwseterrorcallback',['glfwSetErrorCallback',['../group__init.html#gaa5d796c3cf7c1a7f02f845486333fb5f',1,'glfw3.h']]],
  ['glfwsetframebuffersizecallback',['glfwSetFramebufferSizeCallback',['../group__window.html#ga3203461a5303bf289f2e05f854b2f7cf',1,'glfw3.h']]],
  ['glfwsetgamma',['glfwSetGamma',['../group__monitor.html#ga6ac582625c990220785ddd34efa3169a',1,'glfw3.h']]],
  ['glfwsetgammaramp',['glfwSetGammaRamp',['../group__monitor.html#ga583f0ffd0d29613d8cd172b996bbf0dd',1,'glfw3.h']]],
  ['glfwsetinputmode',['glfwSetInputMode',['../group__input.html#gaa92336e173da9c8834558b54ee80563b',1,'glfw3.h']]],
  ['glfwsetjoystickcallback',['glfwSetJoystickCallback',['../group__input.html#gab1dc8379f1b82bb660a6b9c9fa06ca07',1,'glfw3.h']]],
  ['glfwsetkeycallback',['glfwSetKeyCallback',['../group__input.html#ga7e496507126f35ea72f01b2e6ef6d155',1,'glfw3.h']]],
  ['glfwsetmonitorcallback',['glfwSetMonitorCallback',['../group__monitor.html#gac3fe0f647f68b731f99756cd81897378',1,'glfw3.h']]],
  ['glfwsetmousebuttoncallback',['glfwSetMouseButtonCallback',['../group__input.html#gaef49b72d84d615bca0a6ed65485e035d',1,'glfw3.h']]],
  ['glfwsetscrollcallback',['glfwSetScrollCallback',['../group__input.html#gacf02eb10504352f16efda4593c3ce60e',1,'glfw3.h']]],
  ['glfwsettime',['glfwSetTime',['../group__input.html#gaf59589ef6e8b8c8b5ad184b25afd4dc0',1,'glfw3.h']]],
  ['glfwsetwindowaspectratio',['glfwSetWindowAspectRatio',['../group__window.html#ga72ac8cb1ee2e312a878b55153d81b937',1,'glfw3.h']]],
  ['glfwsetwindowclosecallback',['glfwSetWindowCloseCallback',['../group__window.html#gaade9264e79fae52bdb78e2df11ee8d6a',1,'glfw3.h']]],
  ['glfwsetwindowfocuscallback',['glfwSetWindowFocusCallback',['../group__window.html#ga25d1c584edb375d7711c5c3548ba711f',1,'glfw3.h']]],
  ['glfwsetwindowicon',['glfwSetWindowIcon',['../group__window.html#gadd7ccd39fe7a7d1f0904666ae5932dc5',1,'glfw3.h']]],
  ['glfwsetwindowiconifycallback',['glfwSetWindowIconifyCallback',['../group__window.html#gab1ea7263081c0e073b8d5b91d6ffd367',1,'glfw3.h']]],
  ['glfwsetwindowmonitor',['glfwSetWindowMonitor',['../group__window.html#ga81c76c418af80a1cce7055bccb0ae0a7',1,'glfw3.h']]],
  ['glfwsetwindowpos',['glfwSetWindowPos',['../group__window.html#ga1abb6d690e8c88e0c8cd1751356dbca8',1,'glfw3.h']]],
  ['glfwsetwindowposcallback',['glfwSetWindowPosCallback',['../group__window.html#ga2837d4d240659feb4268fcb6530a6ba1',1,'glfw3.h']]],
  ['glfwsetwindowrefreshcallback',['glfwSetWindowRefreshCallback',['../group__window.html#ga4569b76e8ac87c55b53199e6becd97eb',1,'glfw3.h']]],
  ['glfwsetwindowshouldclose',['glfwSetWindowShouldClose',['../group__window.html#ga49c449dde2a6f87d996f4daaa09d6708',1,'glfw3.h']]],
  ['glfwsetwindowsize',['glfwSetWindowSize',['../group__window.html#ga371911f12c74c504dd8d47d832d095cb',1,'glfw3.h']]],
  ['glfwsetwindowsizecallback',['glfwSetWindowSizeCallback',['../group__window.html#gaa40cd24840daa8c62f36cafc847c72b6',1,'glfw3.h']]],
  ['glfwsetwindowsizelimits',['glfwSetWindowSizeLimits',['../group__window.html#gac314fa6cec7d2d307be9963e2709cc90',1,'glfw3.h']]],
  ['glfwsetwindowtitle',['glfwSetWindowTitle',['../group__window.html#ga5d877f09e968cef7a360b513306f17ff',1,'glfw3.h']]],
  ['glfwsetwindowuserpointer',['glfwSetWindowUserPointer',['../group__window.html#ga3d2fc6026e690ab31a13f78bc9fd3651',1,'glfw3.h']]],
  ['glfwshowwindow',['glfwShowWindow',['../group__window.html#ga61be47917b72536a148300f46494fc66',1,'glfw3.h']]],
  ['glfwswapbuffers',['glfwSwapBuffers',['../group__window.html#ga15a5a1ee5b3c2ca6b15ca209a12efd14',1,'glfw3.h']]],
  ['glfwswapinterval',['glfwSwapInterval',['../group__context.html#ga6d4e0cdf151b5e579bd67f13202994ed',1,'glfw3.h']]],
  ['glfwterminate',['glfwTerminate',['../group__init.html#gaaae48c0a18607ea4a4ba951d939f0901',1,'glfw3.h']]],
  ['glfwvulkansupported',['glfwVulkanSupported',['../group__vulkan.html#ga2e7f30931e02464b5bc8d0d4b6f9fe2b',1,'glfw3.h']]],
  ['glfwwaitevents',['glfwWaitEvents',['../group__window.html#ga554e37d781f0a997656c26b2c56c835e',1,'glfw3.h']]],
  ['glfwwaiteventstimeout',['glfwWaitEventsTimeout',['../group__window.html#ga605a178db92f1a7f1a925563ef3ea2cf',1,'glfw3.h']]],
  ['glfwwindowhint',['glfwWindowHint',['../group__window.html#ga7d9c8c62384b1e2821c4dc48952d2033',1,'glfw3.h']]],
  ['glfwwindowshouldclose',['glfwWindowShouldClose',['../group__window.html#ga24e02fbfefbb81fc45320989f8140ab5',1,'glfw3.h']]]
];


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen 1.8.11"/>
<link rel="stylesheet" type="text/css" href="search.css"/>

Loading...

Searching...

No Matches

repo_language: C

mime_type: text/x-c


text:
var searchData=
[
  ['compat_2edox',['compat.dox',['../compat_8dox.html',1,'']]],
  ['compile_2edox',['compile.dox',['../compile_8dox.html',1,'']]],
  ['context_2edox',['context.dox',['../context_8dox.html',1,'']]]
];


text:
var searchData=
[
  ['window_20reference',['Window reference',['../group__window.html',1,'']]]
];


text:
var searchData=
[
  ['bug_20list',['Bug List',['../bug.html',1,'']]],
  ['building_20applications',['Building applications',['../build_guide.html',1,'']]]
];


text:
var searchData=
[
  ['keyboard_20keys',['Keyboard keys',['../group__keys.html',1,'']]]
];


text:
var searchData=
[
  ['pixels',['pixels',['../structGLFWimage.html#a0c532a5c2bb715555279b7817daba0fb',1,'GLFWimage']]]
];


text:
var searchData=
[
  ['input_20guide',['Input guide',['../input_guide.html',1,'']]],
  ['introduction_20to_20the_20api',['Introduction to the API',['../intro_guide.html',1,'']]]
];


text:
/*---------------- Search Box */

#FSearchBox {
    float: left;
}

#MSearchBox {
    white-space : nowrap;
    position: absolute;
    float: none;
    display: inline;
    margin-top: 8px;
    right: 0px;
    width: 170px;
    z-index: 102;
    background-color: white;
}

#MSearchBox .left
{
    display:block;
    position:absolute;
    left:10px;
    width:20px;
    height:19px;
    background:url('search_l.png') no-repeat;
    background-position:right;
}

#MSearchSelect {
    display:block;
    position:absolute;
    width:20px;
    height:19px;
}

.left #MSearchSelect {
    left:4px;
}

.right #MSearchSelect {
    right:5px;
}

#MSearchField {
    display:block;
    position:absolute;
    height:19px;
    background:url('search_m.png') repeat-x;
    border:none;
    width:111px;
    margin-left:20px;
    padding-left:4px;
    color: #909090;
    outline: none;
    font: 9pt Arial, Verdana, sans-serif;
}

#FSearchBox #MSearchField {
    margin-left:15px;
}

#MSearchBox .right {
    display:block;
    position:absolute;
    right:10px;
    top:0px;
    width:20px;
    height:19px;
    background:url('search_r.png') no-repeat;
    background-position:left;
}

#MSearchClose {
    display: none;
    position: absolute;
    top: 4px;
    background : none;
    border: none;
    margin: 0px 4px 0px 0px;
    padding: 0px 0px;
    outline: none;
}

.left #MSearchClose {
    left: 6px;
}

.right #MSearchClose {
    right: 2px;
}

.MSearchBoxActive #MSearchField {
    color: #000000;
}

/*---------------- Search filter selection */

#MSearchSelectWindow {
    display: none;
    position: absolute;
    left: 0; top: 0;
    border: 1px solid #90A5CE;
    background-color: #F9FAFC;
    z-index: 1;
    padding-top: 4px;
    padding-bottom: 4px;
    -moz-border-radius: 4px;
    -webkit-border-top-left-radius: 4px;
    -webkit-border-top-right-radius: 4px;
    -webkit-border-bottom-left-radius: 4px;
    -webkit-border-bottom-right-radius: 4px;
    -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15);
}

.SelectItem {
    font: 8pt Arial, Verdana, sans-serif;
    padding-left:  2px;
    padding-right: 12px;
    border: 0px;
}

span.SelectionMark {
    margin-right: 4px;
    font-family: monospace;
    outline-style: none;
    text-decoration: none;
}

a.SelectItem {
    display: block;
    outline-style: none;
    color: #000000;
    text-decoration: none;
    padding-left:   6px;
    padding-right: 12px;
}

a.SelectItem:focus,
a.SelectItem:active {
    color: #000000;
    outline-style: none;
    text-decoration: none;
}

a.SelectItem:hover {
    color: #FFFFFF;
    background-color: #3D578C;
    outline-style: none;
    text-decoration: none;
    cursor: pointer;
    display: block;
}

/*---------------- Search results window */

iframe#MSearchResults {
    width: 60ex;
    height: 15em;
}

#MSearchResultsWindow {
    display: none;
    position: absolute;
    left: 0; top: 0;
    border: 1px solid #000;
    background-color: #EEF1F7;
}

/* ----------------------------------- */

#SRIndex {
    clear:both;
    padding-bottom: 15px;
}

.SREntry {
    font-size: 10pt;
    padding-left: 1ex;
}

.SRPage .SREntry {
    font-size: 8pt;
    padding: 1px 5px;
}

body.SRPage {
    margin: 5px 2px;
}

.SRChildren {
    padding-left: 3ex; padding-bottom: .5em
}

.SRPage .SRChildren {
    display: none;
}

.SRSymbol {
    font-weight: bold;
    color: #425E97;
    font-family: Arial, Verdana, sans-serif;
    text-decoration: none;
    outline: none;
}

a.SRScope {
    display: block;
    color: #425E97;
    font-family: Arial, Verdana, sans-serif;
    text-decoration: none;
    outline: none;
}

a.SRSymbol:focus, a.SRSymbol:active,
a.SRScope:focus, a.SRScope:active {
    text-decoration: underline;
}

span.SRScope {
    padding-left: 4px;
}

.SRPage .SRStatus {
    padding: 2px 5px;
    font-size: 8pt;
    font-style: italic;
}

.SRResult {
    display: none;
}

DIV.searchresults {
    margin-left: 10px;
    margin-right: 10px;
}

/*---------------- External search page results */

.searchresult {
    background-color: #F0F3F8;
}

.pages b {
   color: white;
   padding: 5px 5px 3px 5px;
   background-image: url("../tab_a.png");
   background-repeat: repeat-x;
   text-shadow: 0 1px 1px #000000;
}

.pages {
    line-height: 17px;
    margin-left: 4px;
    text-decoration: none;
}

.hl {
    font-weight: bold;
}

#searchresults {
    margin-bottom: 20px;
}

.searchpages {
    margin-top: 10px;
}


text:
var searchData=
[
  ['vulkan_2edox',['vulkan.dox',['../vulkan_8dox.html',1,'']]]
];


text:
var searchData=
[
  ['glfw3_2eh',['glfw3.h',['../glfw3_8h.html',1,'']]],
  ['glfw3native_2eh',['glfw3native.h',['../glfw3native_8h.html',1,'']]]
];


text:
var searchData=
[
  ['getting_20started',['Getting started',['../quick_guide.html',1,'']]]
];


text:
var searchData=
[
  ['build_2edox',['build.dox',['../build_8dox.html',1,'']]]
];


text:
var searchData=
[
  ['monitor_20guide',['Monitor guide',['../monitor_guide.html',1,'']]],
  ['moving_20from_20glfw_202_20to_203',['Moving from GLFW 2 to 3',['../moving_guide.html',1,'']]]
];


text:
var searchData=
[
  ['error_20codes',['Error codes',['../group__errors.html',1,'']]]
];


text:
var searchData=
[
  ['input_2edox',['input.dox',['../input_8dox.html',1,'']]],
  ['intro_2edox',['intro.dox',['../intro_8dox.html',1,'']]]
];


text:
var searchData=
[
  ['quick_2edox',['quick.dox',['../quick_8dox.html',1,'']]]
];


text:
var searchData=
[
  ['vulkan_20reference',['Vulkan reference',['../group__vulkan.html',1,'']]],
  ['vulkan_2edox',['vulkan.dox',['../vulkan_8dox.html',1,'']]],
  ['vulkan_20guide',['Vulkan guide',['../vulkan_guide.html',1,'']]]
];


text:
var searchData=
[
  ['joysticks',['Joysticks',['../group__joysticks.html',1,'']]]
];


text:
var searchData=
[
  ['initialization_2c_20version_20and_20error_20reference',['Initialization, version and error reference',['../group__init.html',1,'']]],
  ['input_20reference',['Input reference',['../group__input.html',1,'']]],
  ['input_2edox',['input.dox',['../input_8dox.html',1,'']]],
  ['input_20guide',['Input guide',['../input_guide.html',1,'']]],
  ['intro_2edox',['intro.dox',['../intro_8dox.html',1,'']]],
  ['introduction_20to_20the_20api',['Introduction to the API',['../intro_guide.html',1,'']]]
];


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<title></title>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta name="generator" content="Doxygen 1.8.11"/>
<link rel="stylesheet" type="text/css" href="search.css"/>

Loading...

Searching...

No Matches


text:
var searchData=
[
  ['window_2edox',['window.dox',['../window_8dox.html',1,'']]]
];


text:
var searchData=
[
  ['size',['size',['../structGLFWgammaramp.html#ad620e1cffbff9a32c51bca46301b59a5',1,'GLFWgammaramp']]]
];


text:
# Contribution Guide

## Contents

- [Asking a question](#asking-a-question)
- [Reporting a bug](#reporting-a-bug)
    - [Reporting a compile or link bug](#reporting-a-compile-or-link-bug)
    - [Reporting a segfault or other crash bug](#reporting-a-segfault-or-other-crash-bug)
    - [Reporting a context creation bug](#reporting-a-context-creation-bug)
    - [Reporting a monitor or video mode bug](#reporting-a-monitor-or-video-mode-bug)
    - [Reporting an input or event bug](#reporting-an-input-or-event-bug)
    - [Reporting some other library bug](#reporting-some-other-library-bug)
    - [Reporting a documentation bug](#reporting-a-documentation-bug)
    - [Reporting a website bug](#reporting-a-website-bug)
- [Requesting a feature](#requesting-a-feature)
- [Contributing a bug fix](#contributing-a-bug-fix)
- [Contributing a feature](#contributing-a-feature)

## Asking a question

Questions about how to use GLFW should be asked either in the [support
section](http://discourse.glfw.org/c/support) of the forum, under the [Stack
Overflow tag](https://stackoverflow.com/questions/tagged/glfw) or [Game
Development tag](https://gamedev.stackexchange.com/questions/tagged/glfw) on
Stack Exchange or in the IRC channel `#glfw` on
[Freenode](http://freenode.net/).

Questions about the design or implementation of GLFW or about future plans
should be asked in the [dev section](http://discourse.glfw.org/c/dev) of the
forum or in the IRC channel.  Please don't open a GitHub issue to discuss design
questions without first checking with a maintainer.

## Reporting a bug

If GLFW is behaving unexpectedly at run-time, start by setting an [error
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling).
GLFW will often tell you the cause of an error via this callback.  If it
doesn't, that might be a separate bug.

If GLFW is crashing or triggering asserts, make sure that all your object
handles and other pointers are valid.

For bugs where it makes sense, a [Short, Self Contained, Correct (Compilable),
Example](http://www.sscce.org/) is absolutely invaluable.  Just put it inline in
the body text.  Note that if the bug is reproducible with one of the test
programs that come with GLFW, just mention that instead.

__Don't worry about adding too much information__.  Unimportant information can
be abbreviated or removed later, but missing information can stall bug fixing,
especially when your schedule doesn't align with that of the maintainer.

There are issue labels for both platforms and GPU manufacturers, so there is no
need to mention these in the subject line.  If you do, it will be removed when
the issue is labeled.

If your bug is already reported, please add any new information you have, or if
it already has everything, give it a :+1:.

### Reporting a compile or link bug

__Note:__ GLFW needs many system APIs to do its job, which on some platforms
means linking to many system libraries.  If you are using GLFW as a static
library, that means your application needs to link to these in addition to GLFW.

__Note:__ Check the [Compiling
GLFW](http://www.glfw.org/docs/latest/compile.html) guide and or [Building
applications](http://www.glfw.org/docs/latest/build.html) guide for before
opening an issue of this kind.  Most issues are caused by a missing package or
linker flag.

Always include the __operating system name and version__ (e.g. `Windows
7 64-bit` or `Ubuntu 15.10`) and the __compiler name and version__ (e.g. `Visual
C++ 2015 Update 2`).  If you are using an official release of GLFW,
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
__GLFW commit ID__ (e.g.  `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.

Please also include the __complete build log__ from your compiler and linker,
even if it's long.  It can always be shortened later, if necessary.

#### Quick template

```
OS and version:
Compiler version:
Release or commit:
Build log:
```

### Reporting a segfault or other crash bug

Always include the __operating system name and version__ (e.g. `Windows
7 64-bit` or `Ubuntu 15.10`).  If you are using an official release of GLFW,
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
__GLFW commit ID__ (e.g.  `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.

Please also include any __error messages__ provided to your application via the
[error
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
the __full call stack__ of the crash, or if the crash does not occur in debug
mode, mention that instead.

#### Quick template

```
OS and version:
Release or commit:
Error messages:
Call stack:
```

### Reporting a context creation bug

__Note:__ Windows ships with graphics drivers that do not support OpenGL.  If
GLFW says that your machine lacks support for OpenGL, it very likely does.
Install drivers from the computer manufacturer or graphics card manufacturer
([Nvidia](http://www.geforce.com/drivers),
[AMD](http://support.amd.com/en-us/download),
[Intel](https://www-ssl.intel.com/content/www/us/en/support/detect.html)) to
fix this.

__Note:__ AMD only supports OpenGL ES on Windows via EGL.  See the
[GLFW\_CONTEXT\_CREATION\_API](http://www.glfw.org/docs/latest/window_guide.html#window_hints_ctx)
hint for how to select EGL.

Please verify that context creation also fails with the `glfwinfo` tool before
reporting it as a bug.  This tool is included in the GLFW source tree as
`tests/glfwinfo.c` and is built along with the library.  It has switches for all
GLFW context and framebuffer hints.  Run `glfwinfo -h` for a complete list.

Always include the __operating system name and version__ (e.g. `Windows
7 64-bit` or `Ubuntu 15.10`).  If you are using an official release of GLFW,
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
__GLFW commit ID__ (e.g.  `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.

Please also include the __GLFW version string__ (`3.2.0 X11 EGL clock_gettime
/dev/js XI Xf86vm`), as described
[here](http://www.glfw.org/docs/latest/intro.html#intro_version_string), the
__GPU model and driver version__ (e.g. `GeForce GTX660 with 352.79`), and the
__output of `glfwinfo`__ (with switches matching any hints you set in your
code) when reporting this kind of bug.  If this tool doesn't run on the machine,
mention that instead.

#### Quick template

```
OS and version:
GPU and driver:
Release or commit:
Version string:
glfwinfo output:
```

### Reporting a monitor or video mode bug

__Note:__ On headless systems on some platforms, no monitors are reported.  This
causes glfwGetPrimaryMonitor to return `NULL`, which not all applications are
prepared for.

__Note:__ Some third-party tools report more video modes than are approved of
by the OS.  For safety and compatibility, GLFW only reports video modes the OS
wants programs to use.  This is not a bug.

The `monitors` tool is included in the GLFW source tree as `tests/monitors.c`
and is built along with the library.  It lists all information GLFW provides
about monitors it detects.

Always include the __operating system name and version__ (e.g. `Windows
7 64-bit` or `Ubuntu 15.10`).  If you are using an official release of GLFW,
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
__GLFW commit ID__ (e.g.  `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.

Please also include any __error messages__ provided to your application via the
[error
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
the __output of `monitors`__ when reporting this kind of bug.  If this tool
doesn't run on the machine, mention this instead.

#### Quick template

```
OS and version:
Release or commit:
Error messages:
monitors output:
```

### Reporting an input or event bug

__Note:__ The exact ordering of related window events will sometimes differ.

__Note:__ Window moving and resizing (by the user) will block the main thread on some
platforms.  This is not a bug.  Set a [refresh
callback](http://www.glfw.org/docs/latest/window.html#window_refresh) if you
want to keep the window contents updated during a move or size operation.

The `events` tool is included in the GLFW source tree as `tests/events.c` and is
built along with the library.  It prints all information provided to every
callback supported by GLFW as events occur.  Each event is listed with the time
and a unique number to make discussions about event logs easier.  The tool has
command-line options for creating multiple windows and full screen windows.

Always include the __operating system name and version__ (e.g. `Windows
7 64-bit` or `Ubuntu 15.10`).  If you are using an official release of GLFW,
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
__GLFW commit ID__ (e.g.  `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.

Please also include any __error messages__ provided to your application via the
[error
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling) and
if relevant, the __output of `events`__ when reporting this kind of bug.  If
this tool doesn't run on the machine, mention this instead.

#### Quick template

```
OS and version:
Release or commit:
Error messages:
events output:
```

### Reporting some other library bug

Always include the __operating system name and version__ (e.g. `Windows
7 64-bit` or `Ubuntu 15.10`).  If you are using an official release of GLFW,
include the __GLFW release version__ (e.g. `3.1.2`), otherwise include the
__GLFW commit ID__ (e.g.  `3795d78b14ef06008889cc422a1fb8d642597751`) from Git.

Please also include any __error messages__ provided to your application via the
[error
callback](http://www.glfw.org/docs/latest/intro_guide.html#error_handling), if
relevant.

#### Quick template

```
OS and version:
Release or commit:
Error messages:
```

### Reporting a documentation bug

If you found a bug in the documentation, including this file, then it's fine to
just link to that web page or mention that source file.  You don't need to match
the source to the output or vice versa.

### Reporting a website bug

If the bug is in the documentation (anything under `/docs/`) then please see the
section above.  Bugs in the rest of the site are reported to to the [website
source repository](https://github.com/glfw/website/issues).

## Requesting a feature

Please explain why you need the feature and how you intend to use it.  If you
have a specific API design in mind, please add that as well.  If you have or are
planning to write code for the feature, see the section below.

If there already is a request for the feature you need, add your specific use
case unless it is already mentioned.  If it is, give it a :+1:.

## Contributing a bug fix

__Note:__ You must have all necessary [intellectual
property rights](https://en.wikipedia.org/wiki/Intellectual_property) to any
code you contribute.  If you did not write the code yourself, you must explain
where it came from and under what license you received it.  Even code using the
same license as GLFW may not be copied without attribution.

__There is no preferred patch size__.  A one character fix is just as welcome as
a thousand line one, if that is the appropriate size for the fix.

In addition to the code, a complete bug fix includes:

- Change log entry in `README.md`, describing the incorrect behavior
- Credits entries for all authors of the bug fix

Bug fixes will not be rejected because they don't include all the above parts,
but please keep in mind that maintainer time is finite and that there are many
other bugs and features to work on.

If the patch fixes a bug introduced after the last release, it should not get
a change log entry.

## Contributing a feature

__Note:__ You must have all necessary rights to any code you contribute.  If you
did not write the code yourself, you must explain where it came from and under
what license.  Even code using the same license as GLFW may not be copied
without attribution.

__There is no preferred patch size__.  A one character change is just as welcome
as one adding a thousand line one, if that is the appropriate size for the
feature.

In addition to the code, a complete feature includes:

- Change log entry in `README.md`, listing all new symbols
- News page entry, briefly describing the feature
- Guide documentation, with minimal examples, in the relevant guide
- Reference documentation, with all applicable tags
- Cross-references and mentions in appropriate places
- Credits entries for all authors of the feature

If the feature requires platform-specific code, at minimum stubs must be added
for the new platform function to all supported and experimental platforms.

If it adds a new callback, support for it must be added to `tests/event.c`.

If it adds a new monitor property, support for it must be added to
`tests/monitor.c`.

If it adds a new OpenGL, OpenGL ES or Vulkan option or extension, support
for it must be added to `tests/glfwinfo.c` and the behavior of the library when
the extension is missing documented in `docs/compat.dox`.

Features will not be rejected because they don't include all the above parts,
but please keep in mind that maintainer time is finite and that there are many
other features and bugs to work on.

Please also keep in mind that any part of the public API that has been included
in a release cannot be changed until the next _major_ version.  Features can be
added and existing parts can sometimes be overloaded (in the general sense of
doing more things, not in the C++ sense), but code written to the API of one
minor release should both compile and run on subsequent minor releases.


text:
//========================================================================
// GLFW 3.2 POSIX - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would
//    be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
//    be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
//    distribution.
//
//========================================================================

#ifndef _glfw3_posix_tls_h_
#define _glfw3_posix_tls_h_

#include <pthread.h>

#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsPOSIX posix_tls

// POSIX-specific global TLS data
//
typedef struct _GLFWtlsPOSIX
{
    GLFWbool        allocated;
    pthread_key_t   context;

} _GLFWtlsPOSIX;

GLFWbool _glfwInitThreadLocalStoragePOSIX(void);
void _glfwTerminateThreadLocalStoragePOSIX(void);

#endif // _glfw3_posix_tls_h_


text:
//========================================================================
// GLFW 3.2 Cocoa - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would
//    be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
//    be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
//    distribution.
//
//========================================================================

#include "internal.h"

#include <unistd.h>
#include <ctype.h>
#include <string.h>

#include <mach/mach.h>
#include <mach/mach_error.h>

#include <CoreFoundation/CoreFoundation.h>
#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>

// Joystick element information
//
typedef struct _GLFWjoyelementNS
{
    IOHIDElementRef elementRef;

    long min;
    long max;

    long minReport;
    long maxReport;

} _GLFWjoyelementNS;

static void getElementsCFArrayHandler(const void* value, void* parameter);

// Adds an element to the specified joystick
//
static void addJoystickElement(_GLFWjoystickNS* js,
                               IOHIDElementRef elementRef)
{
    IOHIDElementType elementType;
    long usagePage, usage;
    CFMutableArrayRef elementsArray = NULL;

    elementType = IOHIDElementGetType(elementRef);
    usagePage = IOHIDElementGetUsagePage(elementRef);
    usage = IOHIDElementGetUsage(elementRef);

    if ((elementType != kIOHIDElementTypeInput_Axis) &&
        (elementType != kIOHIDElementTypeInput_Button) &&
        (elementType != kIOHIDElementTypeInput_Misc))
    {
        return;
    }

    switch (usagePage)
    {
        case kHIDPage_GenericDesktop:
        {
            switch (usage)
            {
                case kHIDUsage_GD_X:
                case kHIDUsage_GD_Y:
                case kHIDUsage_GD_Z:
                case kHIDUsage_GD_Rx:
                case kHIDUsage_GD_Ry:
                case kHIDUsage_GD_Rz:
                case kHIDUsage_GD_Slider:
                case kHIDUsage_GD_Dial:
                case kHIDUsage_GD_Wheel:
                    elementsArray = js->axisElements;
                    break;
                case kHIDUsage_GD_Hatswitch:
                    elementsArray = js->hatElements;
                    break;
            }

            break;
        }

        case kHIDPage_Button:
            elementsArray = js->buttonElements;
            break;
        default:
            break;
    }

    if (elementsArray)
    {
        _GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));

        CFArrayAppendValue(elementsArray, element);

        element->elementRef = elementRef;

        element->minReport = IOHIDElementGetLogicalMin(elementRef);
        element->maxReport = IOHIDElementGetLogicalMax(elementRef);
    }
}

// Adds an element to the specified joystick
//
static void getElementsCFArrayHandler(const void* value, void* parameter)
{
    if (CFGetTypeID(value) == IOHIDElementGetTypeID())
    {
        addJoystickElement((_GLFWjoystickNS*) parameter,
                           (IOHIDElementRef) value);
    }
}

// Returns the value of the specified element of the specified joystick
//
static long getElementValue(_GLFWjoystickNS* js, _GLFWjoyelementNS* element)
{
    IOReturn result = kIOReturnSuccess;
    IOHIDValueRef valueRef;
    long value = 0;

    if (js && element && js->deviceRef)
    {
        result = IOHIDDeviceGetValue(js->deviceRef,
                                     element->elementRef,
                                     &valueRef);

        if (kIOReturnSuccess == result)
        {
            value = IOHIDValueGetIntegerValue(valueRef);

            // Record min and max for auto calibration
            if (value < element->minReport)
                element->minReport = value;
            if (value > element->maxReport)
                element->maxReport = value;
        }
    }

    // Auto user scale
    return value;
}

// Removes the specified joystick
//
static void removeJoystick(_GLFWjoystickNS* js)
{
    int i;

    if (!js->present)
        return;

    for (i = 0;  i < CFArrayGetCount(js->axisElements);  i++)
        free((void*) CFArrayGetValueAtIndex(js->axisElements, i));
    CFArrayRemoveAllValues(js->axisElements);
    CFRelease(js->axisElements);

    for (i = 0;  i < CFArrayGetCount(js->buttonElements);  i++)
        free((void*) CFArrayGetValueAtIndex(js->buttonElements, i));
    CFArrayRemoveAllValues(js->buttonElements);
    CFRelease(js->buttonElements);

    for (i = 0;  i < CFArrayGetCount(js->hatElements);  i++)
        free((void*) CFArrayGetValueAtIndex(js->hatElements, i));
    CFArrayRemoveAllValues(js->hatElements);
    CFRelease(js->hatElements);

    free(js->axes);
    free(js->buttons);

    memset(js, 0, sizeof(_GLFWjoystickNS));

    _glfwInputJoystickChange(js - _glfw.ns_js, GLFW_DISCONNECTED);
}

// Polls for joystick axis events and updates GLFW state
//
static GLFWbool pollJoystickAxisEvents(_GLFWjoystickNS* js)
{
    CFIndex i;

    if (!js->present)
        return GLFW_FALSE;

    for (i = 0;  i < CFArrayGetCount(js->axisElements);  i++)
    {
        _GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
            CFArrayGetValueAtIndex(js->axisElements, i);

        long value = getElementValue(js, axis);
        long readScale = axis->maxReport - axis->minReport;

        if (readScale == 0)
            js->axes[i] = value;
        else
            js->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;
    }

    return GLFW_TRUE;
}

// Polls for joystick button events and updates GLFW state
//
static GLFWbool pollJoystickButtonEvents(_GLFWjoystickNS* js)
{
    CFIndex i;
    int buttonIndex = 0;

    if (!js->present)
        return GLFW_FALSE;

    for (i = 0;  i < CFArrayGetCount(js->buttonElements);  i++)
    {
        _GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
            CFArrayGetValueAtIndex(js->buttonElements, i);

        if (getElementValue(js, button))
            js->buttons[buttonIndex++] = GLFW_PRESS;
        else
            js->buttons[buttonIndex++] = GLFW_RELEASE;
    }

    for (i = 0;  i < CFArrayGetCount(js->hatElements);  i++)
    {
        _GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
            CFArrayGetValueAtIndex(js->hatElements, i);

        // Bit fields of button presses for each direction, including nil
        const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };

        long j, value = getElementValue(js, hat);
        if (value < 0 || value > 8)
            value = 8;

        for (j = 0;  j < 4;  j++)
        {
            if (directions[value] & (1 << j))
                js->buttons[buttonIndex++] = GLFW_PRESS;
            else
                js->buttons[buttonIndex++] = GLFW_RELEASE;
        }
    }

    return GLFW_TRUE;
}

// Callback for user-initiated joystick addition
//
static void matchCallback(void* context,
                          IOReturn result,
                          void* sender,
                          IOHIDDeviceRef deviceRef)
{
    _GLFWjoystickNS* js;
    int joy;

    for (joy = GLFW_JOYSTICK_1;  joy <= GLFW_JOYSTICK_LAST;  joy++)
    {
        if (_glfw.ns_js[joy].present && _glfw.ns_js[joy].deviceRef == deviceRef)
            return;
    }

    for (joy = GLFW_JOYSTICK_1;  joy <= GLFW_JOYSTICK_LAST;  joy++)
    {
        if (!_glfw.ns_js[joy].present)
            break;
    }

    if (joy > GLFW_JOYSTICK_LAST)
        return;

    js = _glfw.ns_js + joy;
    js->present = GLFW_TRUE;
    js->deviceRef = deviceRef;

    CFStringRef name = IOHIDDeviceGetProperty(deviceRef,
                                              CFSTR(kIOHIDProductKey));
    if (name)
    {
        CFStringGetCString(name,
                           js->name,
                           sizeof(js->name),
                           kCFStringEncodingUTF8);
    }
    else
        strncpy(js->name, "Unknown", sizeof(js->name));

    js->axisElements = CFArrayCreateMutable(NULL, 0, NULL);
    js->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);
    js->hatElements = CFArrayCreateMutable(NULL, 0, NULL);

    CFArrayRef arrayRef = IOHIDDeviceCopyMatchingElements(deviceRef,
                                                          NULL,
                                                          kIOHIDOptionsTypeNone);
    CFRange range = { 0, CFArrayGetCount(arrayRef) };
    CFArrayApplyFunction(arrayRef,
                         range,
                         getElementsCFArrayHandler,
                         (void*) js);

    CFRelease(arrayRef);

    js->axes = calloc(CFArrayGetCount(js->axisElements), sizeof(float));
    js->buttons = calloc(CFArrayGetCount(js->buttonElements) +
                         CFArrayGetCount(js->hatElements) * 4, 1);

    _glfwInputJoystickChange(joy, GLFW_CONNECTED);
}

// Callback for user-initiated joystick removal
//
static void removeCallback(void* context,
                           IOReturn result,
                           void* sender,
                           IOHIDDeviceRef deviceRef)
{
    int joy;

    for (joy = GLFW_JOYSTICK_1;  joy <= GLFW_JOYSTICK_LAST;  joy++)
    {
        if (_glfw.ns_js[joy].deviceRef == deviceRef)
        {
            removeJoystick(_glfw.ns_js + joy);
            break;
        }
    }
}

// Creates a dictionary to match against devices with the specified usage page
// and usage
//
static CFMutableDictionaryRef createMatchingDictionary(long usagePage,
                                                       long usage)
{
    CFMutableDictionaryRef result =
        CFDictionaryCreateMutable(kCFAllocatorDefault,
                                  0,
                                  &kCFTypeDictionaryKeyCallBacks,
                                  &kCFTypeDictionaryValueCallBacks);

    if (result)
    {
        CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
                                             kCFNumberLongType,
                                             &usagePage);
        if (pageRef)
        {
            CFDictionarySetValue(result,
                                 CFSTR(kIOHIDDeviceUsagePageKey),
                                 pageRef);
            CFRelease(pageRef);

            CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
                                                  kCFNumberLongType,
                                                  &usage);
            if (usageRef)
            {
                CFDictionarySetValue(result,
                                     CFSTR(kIOHIDDeviceUsageKey),
                                     usageRef);
                CFRelease(usageRef);
            }
        }
    }

    return result;
}

//////////////////////////////////////////////////////////////////////////
//////                       GLFW internal API                      //////
//////////////////////////////////////////////////////////////////////////

// Initialize joystick interface
//
void _glfwInitJoysticksNS(void)
{
    CFMutableArrayRef matchingCFArrayRef;

    _glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
                                             kIOHIDOptionsTypeNone);

    matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault,
                                              0,
                                              &kCFTypeArrayCallBacks);
    if (matchingCFArrayRef)
    {
        CFDictionaryRef matchingCFDictRef =
            createMatchingDictionary(kHIDPage_GenericDesktop,
                                     kHIDUsage_GD_Joystick);
        if (matchingCFDictRef)
        {
            CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
            CFRelease(matchingCFDictRef);
        }

        matchingCFDictRef = createMatchingDictionary(kHIDPage_GenericDesktop,
                                                     kHIDUsage_GD_GamePad);
        if (matchingCFDictRef)
        {
            CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
            CFRelease(matchingCFDictRef);
        }

        matchingCFDictRef =
            createMatchingDictionary(kHIDPage_GenericDesktop,
                                     kHIDUsage_GD_MultiAxisController);
        if (matchingCFDictRef)
        {
            CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
            CFRelease(matchingCFDictRef);
        }

        IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager,
                                              matchingCFArrayRef);
        CFRelease(matchingCFArrayRef);
    }

    IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns.hidManager,
                                               &matchCallback, NULL);
    IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns.hidManager,
                                              &removeCallback, NULL);

    IOHIDManagerScheduleWithRunLoop(_glfw.ns.hidManager,
                                    CFRunLoopGetMain(),
                                    kCFRunLoopDefaultMode);

    IOHIDManagerOpen(_glfw.ns.hidManager, kIOHIDOptionsTypeNone);

    // Execute the run loop once in order to register any initially-attached
    // joysticks
    CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
}

// Close all opened joystick handles
//
void _glfwTerminateJoysticksNS(void)
{
    int joy;

    for (joy = GLFW_JOYSTICK_1;  joy <= GLFW_JOYSTICK_LAST;  joy++)
    {
        _GLFWjoystickNS* js = _glfw.ns_js + joy;
        removeJoystick(js);
    }

    CFRelease(_glfw.ns.hidManager);
    _glfw.ns.hidManager = NULL;
}

//////////////////////////////////////////////////////////////////////////
//////                       GLFW platform API                      //////
//////////////////////////////////////////////////////////////////////////

int _glfwPlatformJoystickPresent(int joy)
{
    _GLFWjoystickNS* js = _glfw.ns_js + joy;
    return js->present;
}

const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
{
    _GLFWjoystickNS* js = _glfw.ns_js + joy;
    if (!pollJoystickAxisEvents(js))
        return NULL;

    *count = (int) CFArrayGetCount(js->axisElements);
    return js->axes;
}

const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
{
    _GLFWjoystickNS* js = _glfw.ns_js + joy;
    if (!pollJoystickButtonEvents(js))
        return NULL;

    *count = (int) CFArrayGetCount(js->buttonElements) +
             (int) CFArrayGetCount(js->hatElements) * 4;
    return js->buttons;
}

const char* _glfwPlatformGetJoystickName(int joy)
{
    _GLFWjoystickNS* js = _glfw.ns_js + joy;
    if (!js->present)
        return NULL;

    return js->name;
}


text:
//========================================================================
// GLFW 3.2 Wayland - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would
//    be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
//    be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
//    distribution.
//
//========================================================================

#include "internal.h"

#include <linux/input.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include <wayland-client.h>
#include <wayland-cursor.h>

static inline int min(int n1, int n2)
{
    return n1 < n2 ? n1 : n2;
}

static void pointerHandleEnter(void* data,
                               struct wl_pointer* pointer,
                               uint32_t serial,
                               struct wl_surface* surface,
                               wl_fixed_t sx,
                               wl_fixed_t sy)
{
    _GLFWwindow* window = wl_surface_get_user_data(surface);

    _glfw.wl.pointerSerial = serial;
    _glfw.wl.pointerFocus = window;

    _glfwPlatformSetCursor(window, window->wl.currentCursor);
    _glfwInputCursorEnter(window, GLFW_TRUE);
}

static void pointerHandleLeave(void* data,
                               struct wl_pointer* pointer,
                               uint32_t serial,
                               struct wl_surface* surface)
{
    _GLFWwindow* window = _glfw.wl.pointerFocus;

    if (!window)
        return;

    _glfw.wl.pointerSerial = serial;
    _glfw.wl.pointerFocus = NULL;
    _glfwInputCursorEnter(window, GLFW_FALSE);
}

static void pointerHandleMotion(void* data,
                                struct wl_pointer* pointer,
                                uint32_t time,
                                wl_fixed_t sx,
                                wl_fixed_t sy)
{
    _GLFWwindow* window = _glfw.wl.pointerFocus;

    if (!window)
        return;

    if (window->cursorMode == GLFW_CURSOR_DISABLED)
        return;
    else
    {
        window->wl.cursorPosX = wl_fixed_to_double(sx);
        window->wl.cursorPosY = wl_fixed_to_double(sy);
    }

    _glfwInputCursorPos(window,
                        wl_fixed_to_double(sx),
                        wl_fixed_to_double(sy));
}

static void pointerHandleButton(void* data,
                                struct wl_pointer* wl_pointer,
                                uint32_t serial,
                                uint32_t time,
                                uint32_t button,
                                uint32_t state)
{
    _GLFWwindow* window = _glfw.wl.pointerFocus;
    int glfwButton;

    if (!window)
        return;

    /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
     * codes. */
    glfwButton = button - BTN_LEFT;

    _glfwInputMouseClick(window,
                         glfwButton,
                         state == WL_POINTER_BUTTON_STATE_PRESSED
                                ? GLFW_PRESS
                                : GLFW_RELEASE,
                         _glfw.wl.xkb.modifiers);
}

static void pointerHandleAxis(void* data,
                              struct wl_pointer* wl_pointer,
                              uint32_t time,
                              uint32_t axis,
                              wl_fixed_t value)
{
    _GLFWwindow* window = _glfw.wl.pointerFocus;
    double scroll_factor;
    double x, y;

    if (!window)
        return;

    /* Wayland scroll events are in pointer motion coordinate space (think
     * two finger scroll). The factor 10 is commonly used to convert to
     * "scroll step means 1.0. */
    scroll_factor = 1.0/10.0;

    switch (axis)
    {
        case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
            x = wl_fixed_to_double(value) * scroll_factor;
            y = 0.0;
            break;
        case WL_POINTER_AXIS_VERTICAL_SCROLL:
            x = 0.0;
            y = wl_fixed_to_double(value) * scroll_factor;
            break;
        default:
            break;
    }

    _glfwInputScroll(window, x, y);
}

static const struct wl_pointer_listener pointerListener = {
    pointerHandleEnter,
    pointerHandleLeave,
    pointerHandleMotion,
    pointerHandleButton,
    pointerHandleAxis,
};

static void keyboardHandleKeymap(void* data,
                                 struct wl_keyboard* keyboard,
                                 uint32_t format,
                                 int fd,
                                 uint32_t size)
{
    struct xkb_keymap* keymap;
    struct xkb_state* state;
    char* mapStr;

    if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
    {
        close(fd);
        return;
    }

    mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
    if (mapStr == MAP_FAILED) {
        close(fd);
        return;
    }

    keymap = xkb_map_new_from_string(_glfw.wl.xkb.context,
                                     mapStr,
                                     XKB_KEYMAP_FORMAT_TEXT_V1,
                                     0);
    munmap(mapStr, size);
    close(fd);

    if (!keymap)
    {
        _glfwInputError(GLFW_PLATFORM_ERROR,
                        "Wayland: Failed to compile keymap");
        return;
    }

    state = xkb_state_new(keymap);
    if (!state)
    {
        _glfwInputError(GLFW_PLATFORM_ERROR,
                        "Wayland: Failed to create XKB state");
        xkb_map_unref(keymap);
        return;
    }

    xkb_keymap_unref(_glfw.wl.xkb.keymap);
    xkb_state_unref(_glfw.wl.xkb.state);
    _glfw.wl.xkb.keymap = keymap;
    _glfw.wl.xkb.state = state;

    _glfw.wl.xkb.control_mask =
        1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Control");
    _glfw.wl.xkb.alt_mask =
        1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
    _glfw.wl.xkb.shift_mask =
        1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
    _glfw.wl.xkb.super_mask =
        1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
}

static void keyboardHandleEnter(void* data,
                                struct wl_keyboard* keyboard,
                                uint32_t serial,
                                struct wl_surface* surface,
                                struct wl_array* keys)
{
    _GLFWwindow* window = wl_surface_get_user_data(surface);

    _glfw.wl.keyboardFocus = window;
    _glfwInputWindowFocus(window, GLFW_TRUE);
}

static void keyboardHandleLeave(void* data,
                                struct wl_keyboard* keyboard,
                                uint32_t serial,
                                struct wl_surface* surface)
{
    _GLFWwindow* window = _glfw.wl.keyboardFocus;

    if (!window)
        return;

    _glfw.wl.keyboardFocus = NULL;
    _glfwInputWindowFocus(window, GLFW_FALSE);
}

static int toGLFWKeyCode(uint32_t key)
{
    if (key < sizeof(_glfw.wl.publicKeys) / sizeof(_glfw.wl.publicKeys[0]))
        return _glfw.wl.publicKeys[key];

    return GLFW_KEY_UNKNOWN;
}

static void keyboardHandleKey(void* data,
                              struct wl_keyboard* keyboard,
                              uint32_t serial,
                              uint32_t time,
                              uint32_t key,
                              uint32_t state)
{
    uint32_t code, num_syms;
    long cp;
    int keyCode;
    int action;
    const xkb_keysym_t *syms;
    _GLFWwindow* window = _glfw.wl.keyboardFocus;

    if (!window)
        return;

    keyCode = toGLFWKeyCode(key);
    action = state == WL_KEYBOARD_KEY_STATE_PRESSED
            ? GLFW_PRESS : GLFW_RELEASE;

    _glfwInputKey(window, keyCode, key, action,
                  _glfw.wl.xkb.modifiers);

    code = key + 8;
    num_syms = xkb_key_get_syms(_glfw.wl.xkb.state, code, &syms);

    if (num_syms == 1)
    {
        cp = _glfwKeySym2Unicode(syms[0]);
        if (cp != -1)
        {
            const int mods = _glfw.wl.xkb.modifiers;
            const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
            _glfwInputChar(window, cp, mods, plain);
        }
    }
}

static void keyboardHandleModifiers(void* data,
                                    struct wl_keyboard* keyboard,
                                    uint32_t serial,
                                    uint32_t modsDepressed,
                                    uint32_t modsLatched,
                                    uint32_t modsLocked,
                                    uint32_t group)
{
    xkb_mod_mask_t mask;
    unsigned int modifiers = 0;

    if (!_glfw.wl.xkb.keymap)
        return;

    xkb_state_update_mask(_glfw.wl.xkb.state,
                          modsDepressed,
                          modsLatched,
                          modsLocked,
                          0,
                          0,
                          group);

    mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
                                    XKB_STATE_DEPRESSED |
                                    XKB_STATE_LATCHED);
    if (mask & _glfw.wl.xkb.control_mask)
        modifiers |= GLFW_MOD_CONTROL;
    if (mask & _glfw.wl.xkb.alt_mask)
        modifiers |= GLFW_MOD_ALT;
    if (mask & _glfw.wl.xkb.shift_mask)
        modifiers |= GLFW_MOD_SHIFT;
    if (mask & _glfw.wl.xkb.super_mask)
        modifiers |= GLFW_MOD_SUPER;
    _glfw.wl.xkb.modifiers = modifiers;
}

static const struct wl_keyboard_listener keyboardListener = {
    keyboardHandleKeymap,
    keyboardHandleEnter,
    keyboardHandleLeave,
    keyboardHandleKey,
    keyboardHandleModifiers,
};

static void seatHandleCapabilities(void* data,
                                   struct wl_seat* seat,
                                   enum wl_seat_capability caps)
{
    if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer)
    {
        _glfw.wl.pointer = wl_seat_get_pointer(seat);
        wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL);
    }
    else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer)
    {
        wl_pointer_destroy(_glfw.wl.pointer);
        _glfw.wl.pointer = NULL;
    }

    if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard)
    {
        _glfw.wl.keyboard = wl_seat_get_keyboard(seat);
        wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL);
    }
    else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)
    {
        wl_keyboard_destroy(_glfw.wl.keyboard);
        _glfw.wl.keyboard = NULL;
    }
}

static const struct wl_seat_listener seatListener = {
    seatHandleCapabilities
};

static void registryHandleGlobal(void* data,
                                 struct wl_registry* registry,
                                 uint32_t name,
                                 const char* interface,
                                 uint32_t version)
{
    if (strcmp(interface, "wl_compositor") == 0)
    {
        _glfw.wl.wl_compositor_version = min(3, version);
        _glfw.wl.compositor =
            wl_registry_bind(registry, name, &wl_compositor_interface,
                             _glfw.wl.wl_compositor_version);
    }
    else if (strcmp(interface, "wl_shm") == 0)
    {
        _glfw.wl.shm =
            wl_registry_bind(registry, name, &wl_shm_interface, 1);
    }
    else if (strcmp(interface, "wl_shell") == 0)
    {
        _glfw.wl.shell =
            wl_registry_bind(registry, name, &wl_shell_interface, 1);
    }
    else if (strcmp(interface, "wl_output") == 0)
    {
        _glfwAddOutputWayland(name, version);
    }
    else if (strcmp(interface, "wl_seat") == 0)
    {
        if (!_glfw.wl.seat)
        {
            _glfw.wl.seat =
                wl_registry_bind(registry, name, &wl_seat_interface, 1);
            wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
        }
    }
    else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)
    {
        _glfw.wl.relativePointerManager =
            wl_registry_bind(registry, name,
                             &zwp_relative_pointer_manager_v1_interface,
                             1);
    }
    else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0)
    {
        _glfw.wl.pointerConstraints =
            wl_registry_bind(registry, name,
                             &zwp_pointer_constraints_v1_interface,
                             1);
    }
}

static void registryHandleGlobalRemove(void *data,
                                       struct wl_registry *registry,
                                       uint32_t name)
{
}

static const struct wl_registry_listener registryListener = {
    registryHandleGlobal,
    registryHandleGlobalRemove
};

// Create key code translation tables
//
static void createKeyTables(void)
{
    memset(_glfw.wl.publicKeys, -1, sizeof(_glfw.wl.publicKeys));

    _glfw.wl.publicKeys[KEY_GRAVE]      = GLFW_KEY_GRAVE_ACCENT;
    _glfw.wl.publicKeys[KEY_1]          = GLFW_KEY_1;
    _glfw.wl.publicKeys[KEY_2]          = GLFW_KEY_2;
    _glfw.wl.publicKeys[KEY_3]          = GLFW_KEY_3;
    _glfw.wl.publicKeys[KEY_4]          = GLFW_KEY_4;
    _glfw.wl.publicKeys[KEY_5]          = GLFW_KEY_5;
    _glfw.wl.publicKeys[KEY_6]          = GLFW_KEY_6;
    _glfw.wl.publicKeys[KEY_7]          = GLFW_KEY_7;
    _glfw.wl.publicKeys[KEY_8]          = GLFW_KEY_8;
    _glfw.wl.publicKeys[KEY_9]          = GLFW_KEY_9;
    _glfw.wl.publicKeys[KEY_0]          = GLFW_KEY_0;
    _glfw.wl.publicKeys[KEY_MINUS]      = GLFW_KEY_MINUS;
    _glfw.wl.publicKeys[KEY_EQUAL]      = GLFW_KEY_EQUAL;
    _glfw.wl.publicKeys[KEY_Q]          = GLFW_KEY_Q;
    _glfw.wl.publicKeys[KEY_W]          = GLFW_KEY_W;
    _glfw.wl.publicKeys[KEY_E]          = GLFW_KEY_E;
    _glfw.wl.publicKeys[KEY_R]          = GLFW_KEY_R;
    _glfw.wl.publicKeys[KEY_T]          = GLFW_KEY_T;
    _glfw.wl.publicKeys[KEY_Y]          = GLFW_KEY_Y;
    _glfw.wl.publicKeys[KEY_U]          = GLFW_KEY_U;
    _glfw.wl.publicKeys[KEY_I]          = GLFW_KEY_I;
    _glfw.wl.publicKeys[KEY_O]          = GLFW_KEY_O;
    _glfw.wl.publicKeys[KEY_P]          = GLFW_KEY_P;
    _glfw.wl.publicKeys[KEY_LEFTBRACE]  = GLFW_KEY_LEFT_BRACKET;
    _glfw.wl.publicKeys[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
    _glfw.wl.publicKeys[KEY_A]          = GLFW_KEY_A;
    _glfw.wl.publicKeys[KEY_S]          = GLFW_KEY_S;
    _glfw.wl.publicKeys[KEY_D]          = GLFW_KEY_D;
    _glfw.wl.publicKeys[KEY_F]          = GLFW_KEY_F;
    _glfw.wl.publicKeys[KEY_G]          = GLFW_KEY_G;
    _glfw.wl.publicKeys[KEY_H]          = GLFW_KEY_H;
    _glfw.wl.publicKeys[KEY_J]          = GLFW_KEY_J;
    _glfw.wl.publicKeys[KEY_K]          = GLFW_KEY_K;
    _glfw.wl.publicKeys[KEY_L]          = GLFW_KEY_L;
    _glfw.wl.publicKeys[KEY_SEMICOLON]  = GLFW_KEY_SEMICOLON;
    _glfw.wl.publicKeys[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
    _glfw.wl.publicKeys[KEY_Z]          = GLFW_KEY_Z;
    _glfw.wl.publicKeys[KEY_X]          = GLFW_KEY_X;
    _glfw.wl.publicKeys[KEY_C]          = GLFW_KEY_C;
    _glfw.wl.publicKeys[KEY_V]          = GLFW_KEY_V;
    _glfw.wl.publicKeys[KEY_B]          = GLFW_KEY_B;
    _glfw.wl.publicKeys[KEY_N]          = GLFW_KEY_N;
    _glfw.wl.publicKeys[KEY_M]          = GLFW_KEY_M;
    _glfw.wl.publicKeys[KEY_COMMA]      = GLFW_KEY_COMMA;
    _glfw.wl.publicKeys[KEY_DOT]        = GLFW_KEY_PERIOD;
    _glfw.wl.publicKeys[KEY_SLASH]      = GLFW_KEY_SLASH;
    _glfw.wl.publicKeys[KEY_BACKSLASH]  = GLFW_KEY_BACKSLASH;
    _glfw.wl.publicKeys[KEY_ESC]        = GLFW_KEY_ESCAPE;
    _glfw.wl.publicKeys[KEY_TAB]        = GLFW_KEY_TAB;
    _glfw.wl.publicKeys[KEY_LEFTSHIFT]  = GLFW_KEY_LEFT_SHIFT;
    _glfw.wl.publicKeys[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
    _glfw.wl.publicKeys[KEY_LEFTCTRL]   = GLFW_KEY_LEFT_CONTROL;
    _glfw.wl.publicKeys[KEY_RIGHTCTRL]  = GLFW_KEY_RIGHT_CONTROL;
    _glfw.wl.publicKeys[KEY_LEFTALT]    = GLFW_KEY_LEFT_ALT;
    _glfw.wl.publicKeys[KEY_RIGHTALT]   = GLFW_KEY_RIGHT_ALT;
    _glfw.wl.publicKeys[KEY_LEFTMETA]   = GLFW_KEY_LEFT_SUPER;
    _glfw.wl.publicKeys[KEY_RIGHTMETA]  = GLFW_KEY_RIGHT_SUPER;
    _glfw.wl.publicKeys[KEY_MENU]       = GLFW_KEY_MENU;
    _glfw.wl.publicKeys[KEY_NUMLOCK]    = GLFW_KEY_NUM_LOCK;
    _glfw.wl.publicKeys[KEY_CAPSLOCK]   = GLFW_KEY_CAPS_LOCK;
    _glfw.wl.publicKeys[KEY_PRINT]      = GLFW_KEY_PRINT_SCREEN;
    _glfw.wl.publicKeys[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
    _glfw.wl.publicKeys[KEY_PAUSE]      = GLFW_KEY_PAUSE;
    _glfw.wl.publicKeys[KEY_DELETE]     = GLFW_KEY_DELETE;
    _glfw.wl.publicKeys[KEY_BACKSPACE]  = GLFW_KEY_BACKSPACE;
    _glfw.wl.publicKeys[KEY_ENTER]      = GLFW_KEY_ENTER;
    _glfw.wl.publicKeys[KEY_HOME]       = GLFW_KEY_HOME;
    _glfw.wl.publicKeys[KEY_END]        = GLFW_KEY_END;
    _glfw.wl.publicKeys[KEY_PAGEUP]     = GLFW_KEY_PAGE_UP;
    _glfw.wl.publicKeys[KEY_PAGEDOWN]   = GLFW_KEY_PAGE_DOWN;
    _glfw.wl.publicKeys[KEY_INSERT]     = GLFW_KEY_INSERT;
    _glfw.wl.publicKeys[KEY_LEFT]       = GLFW_KEY_LEFT;
    _glfw.wl.publicKeys[KEY_RIGHT]      = GLFW_KEY_RIGHT;
    _glfw.wl.publicKeys[KEY_DOWN]       = GLFW_KEY_DOWN;
    _glfw.wl.publicKeys[KEY_UP]         = GLFW_KEY_UP;
    _glfw.wl.publicKeys[KEY_F1]         = GLFW_KEY_F1;
    _glfw.wl.publicKeys[KEY_F2]         = GLFW_KEY_F2;
    _glfw.wl.publicKeys[KEY_F3]         = GLFW_KEY_F3;
    _glfw.wl.publicKeys[KEY_F4]         = GLFW_KEY_F4;
    _glfw.wl.publicKeys[KEY_F5]         = GLFW_KEY_F5;
    _glfw.wl.publicKeys[KEY_F6]         = GLFW_KEY_F6;
    _glfw.wl.publicKeys[KEY_F7]         = GLFW_KEY_F7;
    _glfw.wl.publicKeys[KEY_F8]         = GLFW_KEY_F8;
    _glfw.wl.publicKeys[KEY_F9]         = GLFW_KEY_F9;
    _glfw.wl.publicKeys[KEY_F10]        = GLFW_KEY_F10;
    _glfw.wl.publicKeys[KEY_F11]        = GLFW_KEY_F11;
    _glfw.wl.publicKeys[KEY_F12]        = GLFW_KEY_F12;
    _glfw.wl.publicKeys[KEY_F13]        = GLFW_KEY_F13;
    _glfw.wl.publicKeys[KEY_F14]        = GLFW_KEY_F14;
    _glfw.wl.publicKeys[KEY_F15]        = GLFW_KEY_F15;
    _glfw.wl.publicKeys[KEY_F16]        = GLFW_KEY_F16;
    _glfw.wl.publicKeys[KEY_F17]        = GLFW_KEY_F17;
    _glfw.wl.publicKeys[KEY_F18]        = GLFW_KEY_F18;
    _glfw.wl.publicKeys[KEY_F19]        = GLFW_KEY_F19;
    _glfw.wl.publicKeys[KEY_F20]        = GLFW_KEY_F20;
    _glfw.wl.publicKeys[KEY_F21]        = GLFW_KEY_F21;
    _glfw.wl.publicKeys[KEY_F22]        = GLFW_KEY_F22;
    _glfw.wl.publicKeys[KEY_F23]        = GLFW_KEY_F23;
    _glfw.wl.publicKeys[KEY_F24]        = GLFW_KEY_F24;
    _glfw.wl.publicKeys[KEY_KPSLASH]    = GLFW_KEY_KP_DIVIDE;
    _glfw.wl.publicKeys[KEY_KPDOT]      = GLFW_KEY_KP_MULTIPLY;
    _glfw.wl.publicKeys[KEY_KPMINUS]    = GLFW_KEY_KP_SUBTRACT;
    _glfw.wl.publicKeys[KEY_KPPLUS]     = GLFW_KEY_KP_ADD;
    _glfw.wl.publicKeys[KEY_KP0]        = GLFW_KEY_KP_0;
    _glfw.wl.publicKeys[KEY_KP1]        = GLFW_KEY_KP_1;
    _glfw.wl.publicKeys[KEY_KP2]        = GLFW_KEY_KP_2;
    _glfw.wl.publicKeys[KEY_KP3]        = GLFW_KEY_KP_3;
    _glfw.wl.publicKeys[KEY_KP4]        = GLFW_KEY_KP_4;
    _glfw.wl.publicKeys[KEY_KP5]        = GLFW_KEY_KP_5;
    _glfw.wl.publicKeys[KEY_KP6]        = GLFW_KEY_KP_6;
    _glfw.wl.publicKeys[KEY_KP7]        = GLFW_KEY_KP_7;
    _glfw.wl.publicKeys[KEY_KP8]        = GLFW_KEY_KP_8;
    _glfw.wl.publicKeys[KEY_KP9]        = GLFW_KEY_KP_9;
    _glfw.wl.publicKeys[KEY_KPCOMMA]    = GLFW_KEY_KP_DECIMAL;
    _glfw.wl.publicKeys[KEY_KPEQUAL]    = GLFW_KEY_KP_EQUAL;
    _glfw.wl.publicKeys[KEY_KPENTER]    = GLFW_KEY_KP_ENTER;
}

//////////////////////////////////////////////////////////////////////////
//////                       GLFW platform API                      //////
//////////////////////////////////////////////////////////////////////////

int _glfwPlatformInit(void)
{
    _glfw.wl.display = wl_display_connect(NULL);
    if (!_glfw.wl.display)
    {
        _glfwInputError(GLFW_PLATFORM_ERROR,
                        "Wayland: Failed to connect to display");
        return GLFW_FALSE;
    }

    _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
    wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);

    _glfw.wl.monitors = calloc(4, sizeof(_GLFWmonitor*));
    _glfw.wl.monitorsSize = 4;

    createKeyTables();

    _glfw.wl.xkb.context = xkb_context_new(0);
    if (!_glfw.wl.xkb.context)
    {
        _glfwInputError(GLFW_PLATFORM_ERROR,
                        "Wayland: Failed to initialize xkb context");
        return GLFW_FALSE;
    }

    // Sync so we got all registry objects
    wl_display_roundtrip(_glfw.wl.display);

    // Sync so we got all initial output events
    wl_display_roundtrip(_glfw.wl.display);

    if (!_glfwInitThreadLocalStoragePOSIX())
        return GLFW_FALSE;

    if (!_glfwInitJoysticksLinux())
        return GLFW_FALSE;

    _glfwInitTimerPOSIX();

    if (_glfw.wl.pointer && _glfw.wl.shm)
    {
        _glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm);
        if (!_glfw.wl.cursorTheme)
        {
            _glfwInputError(GLFW_PLATFORM_ERROR,
                            "Wayland: Unable to load default cursor theme\n");
            return GLFW_FALSE;
        }
        _glfw.wl.cursorSurface =
            wl_compositor_create_surface(_glfw.wl.compositor);
    }

    return GLFW_TRUE;
}

void _glfwPlatformTerminate(void)
{
    _glfwTerminateEGL();
    _glfwTerminateJoysticksLinux();
    _glfwTerminateThreadLocalStoragePOSIX();

    if (_glfw.wl.cursorTheme)
        wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
    if (_glfw.wl.cursorSurface)
        wl_surface_destroy(_glfw.wl.cursorSurface);
    if (_glfw.wl.registry)
        wl_registry_destroy(_glfw.wl.registry);
    if (_glfw.wl.display)
        wl_display_flush(_glfw.wl.display);
    if (_glfw.wl.display)
        wl_display_disconnect(_glfw.wl.display);
}

const char* _glfwPlatformGetVersionString(void)
{
    return _GLFW_VERSION_NUMBER " Wayland EGL"
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
        " clock_gettime"
#else
        " gettimeofday"
#endif
#if defined(__linux__)
        " /dev/js"
#endif
#if defined(_GLFW_BUILD_DLL)
        " shared"
#endif
        ;
}


text:
//========================================================================
// GLFW 3.2 Mir - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would
//    be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
//    be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
//    distribution.
//
//========================================================================

#include "internal.h"

#include <stdlib.h>

//////////////////////////////////////////////////////////////////////////
//////                       GLFW platform API                      //////
//////////////////////////////////////////////////////////////////////////

_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
{
    int i, found = 0;
    _GLFWmonitor** monitors = NULL;
    MirDisplayConfiguration* displayConfig =
        mir_connection_create_display_config(_glfw.mir.connection);

    *count = 0;

    for (i = 0;  i < displayConfig->num_outputs;  i++)
    {
        const MirDisplayOutput* out = displayConfig->outputs + i;

        if (out->used &&
            out->connected &&
            out->num_modes &&
            out->current_mode < out->num_modes)
        {
            found++;
            monitors        = realloc(monitors, sizeof(_GLFWmonitor*) * found);
            monitors[i]     = _glfwAllocMonitor("Unknown",
                                                out->physical_width_mm,
                                                out->physical_height_mm);

            monitors[i]->mir.x         = out->position_x;
            monitors[i]->mir.y         = out->position_y;
            monitors[i]->mir.output_id = out->output_id;
            monitors[i]->mir.cur_mode  = out->current_mode;

            monitors[i]->modes = _glfwPlatformGetVideoModes(monitors[i],
                                                            &monitors[i]->modeCount);
        }
    }

    mir_display_config_destroy(displayConfig);

    *count = found;
    return monitors;
}

GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
{
    return first->mir.output_id == second->mir.output_id;
}

void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{
    if (xpos)
        *xpos = monitor->mir.x;
    if (ypos)
        *ypos = monitor->mir.y;
}

void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)
{
    switch (pf)
    {
      case mir_pixel_format_rgb_565:
          mode->redBits   = 5;
          mode->greenBits = 6;
          mode->blueBits  = 5;
          break;
      case mir_pixel_format_rgba_5551:
          mode->redBits   = 5;
          mode->greenBits = 5;
          mode->blueBits  = 5;
          break;
      case mir_pixel_format_rgba_4444:
          mode->redBits   = 4;
          mode->greenBits = 4;
          mode->blueBits  = 4;
          break;
      case mir_pixel_format_abgr_8888:
      case mir_pixel_format_xbgr_8888:
      case mir_pixel_format_argb_8888:
      case mir_pixel_format_xrgb_8888:
      case mir_pixel_format_bgr_888:
      case mir_pixel_format_rgb_888:
      default:
          mode->redBits   = 8;
          mode->greenBits = 8;
          mode->blueBits  = 8;
          break;
    }
}

GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
{
    int i;
    GLFWvidmode* modes = NULL;
    MirDisplayConfiguration* displayConfig =
        mir_connection_create_display_config(_glfw.mir.connection);

    for (i = 0;  i < displayConfig->num_outputs;  i++)
    {
        const MirDisplayOutput* out = displayConfig->outputs + i;
        if (out->output_id != monitor->mir.output_id)
            continue;

        modes = calloc(out->num_modes, sizeof(GLFWvidmode));

        for (*found = 0;  *found < out->num_modes;  (*found)++)
        {
            modes[*found].width  = out->modes[*found].horizontal_resolution;
            modes[*found].height = out->modes[*found].vertical_resolution;
            modes[*found].refreshRate = out->modes[*found].refresh_rate;

            FillInRGBBitsFromPixelFormat(&modes[*found], out->output_formats[*found]);
        }

        break;
    }

    mir_display_config_destroy(displayConfig);

    return modes;
}

void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
{
    *mode = monitor->modes[monitor->mir.cur_mode];
}

void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
    _glfwInputError(GLFW_PLATFORM_ERROR,
                    "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}

void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{
    _glfwInputError(GLFW_PLATFORM_ERROR,
                    "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}

//////////////////////////////////////////////////////////////////////////
//////                        GLFW native API                       //////
//////////////////////////////////////////////////////////////////////////

GLFWAPI int glfwGetMirMonitor(GLFWmonitor* handle)
{
    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
    _GLFW_REQUIRE_INIT_OR_RETURN(0);
    return monitor->mir.output_id;
}


text:
//========================================================================
// GLFW 3.2 Win32 - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would
//    be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
//    be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
//    distribution.
//
//========================================================================

#include "internal.h"

#include <stdlib.h>
#include <malloc.h>

#include <initguid.h>
DEFINE_GUID(GUID_DEVINTERFACE_HID,0x4d1e55b2,0xf16f,0x11cf,0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30);

#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)

// Applications exporting this symbol with this value will be automatically
// directed to the high-performance GPU on Nvidia Optimus systems with
// up-to-date drivers
//
__declspec(dllexport) DWORD NvOptimusEnablement = 1;

// Applications exporting this symbol with this value will be automatically
// directed to the high-performance GPU on AMD PowerXpress systems with
// up-to-date drivers
//
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;

#endif // _GLFW_USE_HYBRID_HPG

#if defined(_GLFW_BUILD_DLL)

// GLFW DLL entry point
//
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
{
    return TRUE;
}

#endif // _GLFW_BUILD_DLL

// Load necessary libraries (DLLs)
//
static GLFWbool loadLibraries(void)
{
    _glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
    if (!_glfw.win32.winmm.instance)
    {
        _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll");
        return GLFW_FALSE;
    }

    _glfw.win32.winmm.timeGetTime = (TIMEGETTIME_T)
        GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");

    _glfw.win32.user32.instance = LoadLibraryA("user32.dll");
    if (!_glfw.win32.user32.instance)
    {
        _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll");
        return GLFW_FALSE;
    }

    _glfw.win32.user32.SetProcessDPIAware = (SETPROCESSDPIAWARE_T)
        GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
    _glfw.win32.user32.ChangeWindowMessageFilterEx = (CHANGEWINDOWMESSAGEFILTEREX_T)
        GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");

    _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
    if (_glfw.win32.dinput8.instance)
    {
        _glfw.win32.dinput8.DirectInput8Create = (DIRECTINPUT8CREATE_T)
            GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
    }

    {
        int i;
        const char* names[] =
        {
            "xinput1_4.dll",
            "xinput1_3.dll",
            "xinput9_1_0.dll",
            "xinput1_2.dll",
            "xinput1_1.dll",
            NULL
        };

        for (i = 0;  names[i];  i++)
        {
            _glfw.win32.xinput.instance = LoadLibraryA(names[i]);
            if (_glfw.win32.xinput.instance)
            {
                _glfw.win32.xinput.XInputGetCapabilities = (XINPUTGETCAPABILITIES_T)
                    GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
                _glfw.win32.xinput.XInputGetState = (XINPUTGETSTATE_T)
                    GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");

                break;
            }
        }
    }

    _glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
    if (_glfw.win32.dwmapi.instance)
    {
        _glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T)
            GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
        _glfw.win32.dwmapi.DwmFlush = (DWMFLUSH_T)
            GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
    }

    _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
    if (_glfw.win32.shcore.instance)
    {
        _glfw.win32.shcore.SetProcessDpiAwareness = (SETPROCESSDPIAWARENESS_T)
            GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
    }

    return GLFW_TRUE;
}

// Unload used libraries (DLLs)
//
static void freeLibraries(void)
{
    if (_glfw.win32.xinput.instance)
        FreeLibrary(_glfw.win32.xinput.instance);

    if (_glfw.win32.dinput8.instance)
        FreeLibrary(_glfw.win32.dinput8.instance);

    if (_glfw.win32.winmm.instance)
        FreeLibrary(_glfw.win32.winmm.instance);

    if (_glfw.win32.user32.instance)
        FreeLibrary(_glfw.win32.user32.instance);

    if (_glfw.win32.dwmapi.instance)
        FreeLibrary(_glfw.win32.dwmapi.instance);

    if (_glfw.win32.shcore.instance)
        FreeLibrary(_glfw.win32.shcore.instance);
}

// Create key code translation tables
//
static void createKeyTables(void)
{
    int scancode;

    memset(_glfw.win32.publicKeys, -1, sizeof(_glfw.win32.publicKeys));
    memset(_glfw.win32.nativeKeys, -1, sizeof(_glfw.win32.nativeKeys));

    _glfw.win32.publicKeys[0x00B] = GLFW_KEY_0;
    _glfw.win32.publicKeys[0x002] = GLFW_KEY_1;
    _glfw.win32.publicKeys[0x003] = GLFW_KEY_2;
    _glfw.win32.publicKeys[0x004] = GLFW_KEY_3;
    _glfw.win32.publicKeys[0x005] = GLFW_KEY_4;
    _glfw.win32.publicKeys[0x006] = GLFW_KEY_5;
    _glfw.win32.publicKeys[0x007] = GLFW_KEY_6;
    _glfw.win32.publicKeys[0x008] = GLFW_KEY_7;
    _glfw.win32.publicKeys[0x009] = GLFW_KEY_8;
    _glfw.win32.publicKeys[0x00A] = GLFW_KEY_9;
    _glfw.win32.publicKeys[0x01E] = GLFW_KEY_A;
    _glfw.win32.publicKeys[0x030] = GLFW_KEY_B;
    _glfw.win32.publicKeys[0x02E] = GLFW_KEY_C;
    _glfw.win32.publicKeys[0x020] = GLFW_KEY_D;
    _glfw.win32.publicKeys[0x012] = GLFW_KEY_E;
    _glfw.win32.publicKeys[0x021] = GLFW_KEY_F;
    _glfw.win32.publicKeys[0x022] = GLFW_KEY_G;
    _glfw.win32.publicKeys[0x023] = GLFW_KEY_H;
    _glfw.win32.publicKeys[0x017] = GLFW_KEY_I;
    _glfw.win32.publicKeys[0x024] = GLFW_KEY_J;
    _glfw.win32.publicKeys[0x025] = GLFW_KEY_K;
    _glfw.win32.publicKeys[0x026] = GLFW_KEY_L;
    _glfw.win32.publicKeys[0x032] = GLFW_KEY_M;
    _glfw.win32.publicKeys[0x031] = GLFW_KEY_N;
    _glfw.win32.publicKeys[0x018] = GLFW_KEY_O;
    _glfw.win32.publicKeys[0x019] = GLFW_KEY_P;
    _glfw.win32.publicKeys[0x010] = GLFW_KEY_Q;
    _glfw.win32.publicKeys[0x013] = GLFW_KEY_R;
    _glfw.win32.publicKeys[0x01F] = GLFW_KEY_S;
    _glfw.win32.publicKeys[0x014] = GLFW_KEY_T;
    _glfw.win32.publicKeys[0x016] = GLFW_KEY_U;
    _glfw.win32.publicKeys[0x02F] = GLFW_KEY_V;
    _glfw.win32.publicKeys[0x011] = GLFW_KEY_W;
    _glfw.win32.publicKeys[0x02D] = GLFW_KEY_X;
    _glfw.win32.publicKeys[0x015] = GLFW_KEY_Y;
    _glfw.win32.publicKeys[0x02C] = GLFW_KEY_Z;

    _glfw.win32.publicKeys[0x028] = GLFW_KEY_APOSTROPHE;
    _glfw.win32.publicKeys[0x02B] = GLFW_KEY_BACKSLASH;
    _glfw.win32.publicKeys[0x033] = GLFW_KEY_COMMA;
    _glfw.win32.publicKeys[0x00D] = GLFW_KEY_EQUAL;
    _glfw.win32.publicKeys[0x029] = GLFW_KEY_GRAVE_ACCENT;
    _glfw.win32.publicKeys[0x01A] = GLFW_KEY_LEFT_BRACKET;
    _glfw.win32.publicKeys[0x00C] = GLFW_KEY_MINUS;
    _glfw.win32.publicKeys[0x034] = GLFW_KEY_PERIOD;
    _glfw.win32.publicKeys[0x01B] = GLFW_KEY_RIGHT_BRACKET;
    _glfw.win32.publicKeys[0x027] = GLFW_KEY_SEMICOLON;
    _glfw.win32.publicKeys[0x035] = GLFW_KEY_SLASH;
    _glfw.win32.publicKeys[0x056] = GLFW_KEY_WORLD_2;

    _glfw.win32.publicKeys[0x00E] = GLFW_KEY_BACKSPACE;
    _glfw.win32.publicKeys[0x153] = GLFW_KEY_DELETE;
    _glfw.win32.publicKeys[0x14F] = GLFW_KEY_END;
    _glfw.win32.publicKeys[0x01C] = GLFW_KEY_ENTER;
    _glfw.win32.publicKeys[0x001] = GLFW_KEY_ESCAPE;
    _glfw.win32.publicKeys[0x147] = GLFW_KEY_HOME;
    _glfw.win32.publicKeys[0x152] = GLFW_KEY_INSERT;
    _glfw.win32.publicKeys[0x15D] = GLFW_KEY_MENU;
    _glfw.win32.publicKeys[0x151] = GLFW_KEY_PAGE_DOWN;
    _glfw.win32.publicKeys[0x149] = GLFW_KEY_PAGE_UP;
    _glfw.win32.publicKeys[0x045] = GLFW_KEY_PAUSE;
    _glfw.win32.publicKeys[0x146] = GLFW_KEY_PAUSE;
    _glfw.win32.publicKeys[0x039] = GLFW_KEY_SPACE;
    _glfw.win32.publicKeys[0x00F] = GLFW_KEY_TAB;
    _glfw.win32.publicKeys[0x03A] = GLFW_KEY_CAPS_LOCK;
    _glfw.win32.publicKeys[0x145] = GLFW_KEY_NUM_LOCK;
    _glfw.win32.publicKeys[0x046] = GLFW_KEY_SCROLL_LOCK;
    _glfw.win32.publicKeys[0x03B] = GLFW_KEY_F1;
    _glfw.win32.publicKeys[0x03C] = GLFW_KEY_F2;
    _glfw.win32.publicKeys[0x03D] = GLFW_KEY_F3;
    _glfw.win32.publicKeys[0x03E] = GLFW_KEY_F4;
    _glfw.win32.publicKeys[0x03F] = GLFW_KEY_F5;
    _glfw.win32.publicKeys[0x040] = GLFW_KEY_F6;
    _glfw.win32.publicKeys[0x041] = GLFW_KEY_F7;
    _glfw.win32.publicKeys[0x042] = GLFW_KEY_F8;
    _glfw.win32.publicKeys[0x043] = GLFW_KEY_F9;
    _glfw.win32.publicKeys[0x044] = GLFW_KEY_F10;
    _glfw.win32.publicKeys[0x057] = GLFW_KEY_F11;
    _glfw.win32.publicKeys[0x058] = GLFW_KEY_F12;
    _glfw.win32.publicKeys[0x064] = GLFW_KEY_F13;
    _glfw.win32.publicKeys[0x065] = GLFW_KEY_F14;
    _glfw.win32.publicKeys[0x066] = GLFW_KEY_F15;
    _glfw.win32.publicKeys[0x067] = GLFW_KEY_F16;
    _glfw.win32.publicKeys[0x068] = GLFW_KEY_F17;
    _glfw.win32.publicKeys[0x069] = GLFW_KEY_F18;
    _glfw.win32.publicKeys[0x06A] = GLFW_KEY_F19;
    _glfw.win32.publicKeys[0x06B] = GLFW_KEY_F20;
    _glfw.win32.publicKeys[0x06C] = GLFW_KEY_F21;
    _glfw.win32.publicKeys[0x06D] = GLFW_KEY_F22;
    _glfw.win32.publicKeys[0x06E] = GLFW_KEY_F23;
    _glfw.win32.publicKeys[0x076] = GLFW_KEY_F24;
    _glfw.win32.publicKeys[0x038] = GLFW_KEY_LEFT_ALT;
    _glfw.win32.publicKeys[0x01D] = GLFW_KEY_LEFT_CONTROL;
    _glfw.win32.publicKeys[0x02A] = GLFW_KEY_LEFT_SHIFT;
    _glfw.win32.publicKeys[0x15B] = GLFW_KEY_LEFT_SUPER;
    _glfw.win32.publicKeys[0x137] = GLFW_KEY_PRINT_SCREEN;
    _glfw.win32.publicKeys[0x138] = GLFW_KEY_RIGHT_ALT;
    _glfw.win32.publicKeys[0x11D] = GLFW_KEY_RIGHT_CONTROL;
    _glfw.win32.publicKeys[0x036] = GLFW_KEY_RIGHT_SHIFT;
    _glfw.win32.publicKeys[0x15C] = GLFW_KEY_RIGHT_SUPER;
    _glfw.win32.publicKeys[0x150] = GLFW_KEY_DOWN;
    _glfw.win32.publicKeys[0x14B] = GLFW_KEY_LEFT;
    _glfw.win32.publicKeys[0x14D] = GLFW_KEY_RIGHT;
    _glfw.win32.publicKeys[0x148] = GLFW_KEY_UP;

    _glfw.win32.publicKeys[0x052] = GLFW_KEY_KP_0;
    _glfw.win32.publicKeys[0x04F] = GLFW_KEY_KP_1;
    _glfw.win32.publicKeys[0x050] = GLFW_KEY_KP_2;
    _glfw.win32.publicKeys[0x051] = GLFW_KEY_KP_3;
    _glfw.win32.publicKeys[0x04B] = GLFW_KEY_KP_4;
    _glfw.win32.publicKeys[0x04C] = GLFW_KEY_KP_5;
    _glfw.win32.publicKeys[0x04D] = GLFW_KEY_KP_6;
    _glfw.win32.publicKeys[0x047] = GLFW_KEY_KP_7;
    _glfw.win32.publicKeys[0x048] = GLFW_KEY_KP_8;
    _glfw.win32.publicKeys[0x049] = GLFW_KEY_KP_9;
    _glfw.win32.publicKeys[0x04E] = GLFW_KEY_KP_ADD;
    _glfw.win32.publicKeys[0x053] = GLFW_KEY_KP_DECIMAL;
    _glfw.win32.publicKeys[0x135] = GLFW_KEY_KP_DIVIDE;
    _glfw.win32.publicKeys[0x11C] = GLFW_KEY_KP_ENTER;
    _glfw.win32.publicKeys[0x037] = GLFW_KEY_KP_MULTIPLY;
    _glfw.win32.publicKeys[0x04A] = GLFW_KEY_KP_SUBTRACT;

    for (scancode = 0;  scancode < 512;  scancode++)
    {
        if (_glfw.win32.publicKeys[scancode] > 0)
            _glfw.win32.nativeKeys[_glfw.win32.publicKeys[scancode]] = scancode;
    }
}

// Creates a dummy window for behind-the-scenes work
//
static HWND createHelperWindow(void)
{
    HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
                                  _GLFW_WNDCLASSNAME,
                                  L"GLFW helper window",
                                  WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
                                  0, 0, 1, 1,
                                  HWND_MESSAGE, NULL,
                                  GetModuleHandleW(NULL),
                                  NULL);
    if (!window)
    {
        _glfwInputError(GLFW_PLATFORM_ERROR,
                        "Win32: Failed to create helper window");
        return NULL;
    }

    // HACK: The first call to ShowWindow is ignored if the parent process
    //       passed along a STARTUPINFO, so clear that flag with a no-op call
    ShowWindow(window, SW_HIDE);

    // Register for HID device notifications
    {
        DEV_BROADCAST_DEVICEINTERFACE_W dbi;
        ZeroMemory(&dbi, sizeof(dbi));
        dbi.dbcc_size = sizeof(dbi);
        dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
        dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;

        RegisterDeviceNotificationW(window,
                                    (DEV_BROADCAST_HDR*) &dbi,
                                    DEVICE_NOTIFY_WINDOW_HANDLE);
    }

   return window;
}

//////////////////////////////////////////////////////////////////////////
//////                       GLFW internal API                      //////
//////////////////////////////////////////////////////////////////////////

// Returns a wide string version of the specified UTF-8 string
//
WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
{
    WCHAR* target;
    int length;

    length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
    if (!length)
        return NULL;

    target = calloc(length, sizeof(WCHAR));

    if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length))
    {
        free(target);
        return NULL;
    }

    return target;
}

// Returns a UTF-8 string version of the specified wide string
//
char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
{
    char* target;
    int length;

    length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
    if (!length)
        return NULL;

    target = calloc(length, 1);

    if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length, NULL, NULL))
    {
        free(target);
        return NULL;
    }

    return target;
}

//////////////////////////////////////////////////////////////////////////
//////                       GLFW platform API                      //////
//////////////////////////////////////////////////////////////////////////

int _glfwPlatformInit(void)
{
    if (!_glfwInitThreadLocalStorageWin32())
        return GLFW_FALSE;

    // To make SetForegroundWindow work as we want, we need to fiddle
    // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
    // as possible in the hope of still being the foreground process)
    SystemParametersInfoW(SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
                          &_glfw.win32.foregroundLockTimeout, 0);
    SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0),
                          SPIF_SENDCHANGE);

    if (!loadLibraries())
        return GLFW_FALSE;

    createKeyTables();

    if (_glfw_SetProcessDpiAwareness)
        _glfw_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
    else if (_glfw_SetProcessDPIAware)
        _glfw_SetProcessDPIAware();

    if (!_glfwRegisterWindowClassWin32())
        return GLFW_FALSE;

    _glfw.win32.helperWindowHandle = createHelperWindow();
    if (!_glfw.win32.helperWindowHandle)
        return GLFW_FALSE;

    _glfwPlatformPollEvents();

    _glfwInitTimerWin32();
    _glfwInitJoysticksWin32();

    return GLFW_TRUE;
}

void _glfwPlatformTerminate(void)
{
    if (_glfw.win32.helperWindowHandle)
        DestroyWindow(_glfw.win32.helperWindowHandle);

    _glfwUnregisterWindowClassWin32();

    // Restore previous foreground lock timeout system setting
    SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
                          UIntToPtr(_glfw.win32.foregroundLockTimeout),
                          SPIF_SENDCHANGE);

    free(_glfw.win32.clipboardString);

    _glfwTerminateWGL();
    _glfwTerminateEGL();

    _glfwTerminateJoysticksWin32();
    _glfwTerminateThreadLocalStorageWin32();

    freeLibraries();
}

const char* _glfwPlatformGetVersionString(void)
{
    return _GLFW_VERSION_NUMBER " Win32 WGL EGL"
#if defined(__MINGW32__)
        " MinGW"
#elif defined(_MSC_VER)
        " VisualC"
#endif
#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
        " hybrid-GPU"
#endif
#if defined(_GLFW_BUILD_DLL)
        " DLL"
#endif
        ;
}