diff --git a/CMake/CheckX11Extensions.cmake b/CMake/CheckX11Extensions.cmake
new file mode 100644
index 00000000..a6f9b18b
--- /dev/null
+++ b/CMake/CheckX11Extensions.cmake
@@ -0,0 +1,88 @@
+# - Check if X11 RandR extension is available
+# Check if the X11 extension RandR is available.
+# This macro defines :
+# - X11_RANDR_FOUND, If set to NO RandR is not available.
+# - X11_RANDR_INCLUDE_DIR, includes directory containing the RandR header.
+# - X11_RANDR_LIBRARIES, libraries to link in the library to use RandR.
+#
+# Created by Olivier Delannoy.
+macro(CHECK_X11_XRANDR)
+ message(STATUS "Checking for X11 extension XRandR")
+ set(X11_XRANDR_FOUND "NO")
+ find_path(X11_XRANDR_INCLUDE_DIR "X11/extensions/Xrandr.h"
+ PATHS
+ /usr/local/include
+ /usr/local/X11/include
+ /usr/local/X11R6/include
+ /usr/include
+ /usr/X11/include
+ /usr/X11R6/include)
+
+ find_library(X11_XRANDR_LIBRARIES NAMES Xrandr
+ PATHS
+ /usr/local/lib
+ /usr/local/X11/lib
+ /usr/local/X11R6/lib
+ /usr/lib
+ /usr/X11/lib
+ /usr/X11R6/lib)
+ # Create check if file compiles with randr
+
+ if (X11_XRANDR_LIBRARIES AND X11_XRANDR_INCLUDE_DIR)
+ set(X11_XRANDR_FOUND "YES")
+ endif (X11_XRANDR_LIBRARIES AND X11_XRANDR_INCLUDE_DIR)
+
+ if (X11_XRANDR_FOUND)
+ message(STATUS "Checking for X11 extension XRandR -- found")
+ else (X11_XRANDR_FOUND)
+ message(STATUS "Checking for X11 extension XRandR -- not found")
+ endif (X11_XRANDR_FOUND)
+
+ mark_as_advanced(X11_XRANDR_LIBRARIES X11_XRANDR_INCLUDE_DIR)
+endmacro(CHECK_X11_XRANDR)
+
+
+# - Check if X11 VidMod extension is available
+# Check if the X11 extension VidMod is available.
+# This macro defines :
+# - X11_VIDMOD_FOUND, If set to NO VidMod is not available.
+# - X11_VIDMOD_INCLUDE_DIR, includes directory containing the headers.
+# - X11_VIDMOD_LIBRARIES, libraries to link in the libraries.
+#
+# Created by Olivier Delannoy.
+macro(CHECK_X11_XF86VIDMODE)
+ message(STATUS "Checking for X11 extension xf86vidmode")
+ set(X11_XF86VIDMODE_FOUND "NO")
+ find_path(X11_XF86VIDMODE_INCLUDE_DIR "X11/extensions/xf86vmode.h"
+ PATHS
+ /usr/local/include
+ /usr/local/X11/include
+ /usr/local/X11R6/include
+ /usr/include
+ /usr/X11/include
+ /usr/X11R6/include)
+
+ find_library(X11_XF86VIDMODE_LIBRARIES NAMES Xxf86vm PATHS
+ /usr/local/lib
+ /usr/local/X11/lib
+ /usr/local/X11R6/lib
+ /usr/lib
+ /usr/X11/lib
+ /usr/X11R6/lib)
+ # Add a test case here
+ if (X11_XF86VIDMODE_LIBRARIES AND X11_XF86VIDMODE_INCLUDE_DIR)
+ set(X11_XF86VIDMODE_FOUND "YES")
+ endif (X11_XF86VIDMODE_LIBRARIES AND X11_XF86VIDMODE_INCLUDE_DIR)
+
+ if (X11_XF86VIDMODE_FOUND)
+ message(STATUS "Checking for X11 extension xf86vidmode -- found")
+ else (X11_XF86VIDMODE_FOUND)
+ message(STATUS "Checking for X11 extension xf86vidmode -- not found")
+ endif(X11_XF86VIDMODE_FOUND)
+
+ mark_as_advanced(
+ X11_XF86VIDMODE_LIBRARIES
+ X11_XF86VIDMODE_INCLUDE_DIR
+ )
+
+endmacro(CHECK_X11_XF86VIDMODE)
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 00000000..7acc5af1
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,163 @@
+project(GLFW C)
+
+set(GLFW_VERSION_MAJOR "2")
+set(GLFW_VERSION_MINOR "7")
+set(GLFW_VERSION_PATCH "0")
+set(GLFW_VERSION_EXTRA "")
+set(GLFW_VERSION "${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}")
+set(GLFW_VERSION_FULL
+ "${GLFW_VERSION}.${GLFW_VERSION_PATCH}${GLFW_VERSION_EXTRA}")
+
+cmake_minimum_required(VERSION 2.4)
+
+include(CheckFunctionExists)
+include(CheckSymbolExists)
+
+# Stuff common to all platform
+find_package(OpenGL REQUIRED)
+
+set(common_SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib/enable.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib/fullscreen.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib/glext.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib/init.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib/input.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib/joystick.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib/time.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib/window.c
+)
+
+# Stuff specific to WGL on Win32
+if (WIN32)
+ message(STATUS "Building GLFW for WGL on a Win32 system")
+
+ # Set up library and include paths
+ set(CMAKE_REQUIRED_LIBRARIES ${OPENGL_gl_LIBRARY})
+ list(APPEND GLFW_INCLUDE_DIR ${OPENGL_INCLUDE_DIR})
+ list(APPEND GLFW_LIBRARIES ${OPENGL_gl_LIBRARY})
+
+ # Select platform specific code
+ add_subdirectory(lib/win32)
+endif (WIN32)
+
+# Stuff specific to GLX on Unix-like platforms
+if (UNIX AND NOT APPLE AND NOT CYGWIN)
+ message(STATUS "Building GLFW for GLX on a Unix-like system")
+
+ # Set up library and include paths
+ set(CMAKE_REQUIRED_LIBRARIES ${X11_X11_LIB} ${OPENGL_gl_LIBRARY})
+ list(APPEND GLFW_INCLUDE_DIR ${X11_X11_INCLUDE_PATH})
+ list(APPEND GLFW_LIBRARIES ${X11_X11_LIB})
+ list(APPEND GLFW_INCLUDE_DIR ${OPENGL_INCLUDE_DIR})
+ list(APPEND GLFW_LIBRARIES ${OPENGL_gl_LIBRARY})
+
+ # Detect X11 extension
+ include(${CMAKE_CURRENT_SOURCE_DIR}/CMake/CheckX11Extensions.cmake)
+
+ # Check for XRandR (modern resolution switching extension)
+ CHECK_X11_XRANDR()
+ if (X11_XRANDR_FOUND)
+ set(_GLFW_HAS_XRANDR 1)
+ list(APPEND GLFW_INCLUDE_DIR ${X11_XRANDR_INCLUDE_DIR})
+ list(APPEND GLFW_LIBRARIES ${X11_XRANDR_LIBRARIES})
+ endif(X11_XRANDR_FOUND)
+
+ # Check for xf86vidmode (fallback legacy resolution switching extension)
+ if (NOT X11_XRANDR_FOUND)
+ CHECK_X11_XF86VIDMODE()
+ if (X11_XF86VIDMODE_FOUND)
+ set(_GLFW_HAS_XF86VIDMODE 1)
+ list(APPEND GLFW_INCLUDE_DIR ${X11_XF86VIDMODE_INCLUDE_DIR})
+ list(APPEND GLFW_LIBRARIES ${X11_XF86VIDMODE_LIBRARIES})
+ endif(X11_XF86VIDMODE_FOUND)
+ endif (NOT X11_XRANDR_FOUND)
+
+ CHECK_FUNCTION_EXISTS(glXGetProcAddress _GLFW_HAS_GLXGETPROCADDRESS)
+
+ if (NOT _GLFW_HAS_GLXGETPROCADDRESS)
+ CHECK_FUNCTION_EXISTS(glXGetProcAddressARB _GLFW_HAS_GLXGETPROCADDRESSARB)
+ endif (NOT _GLFW_HAS_GLXGETPROCADDRESS)
+
+ if (NOT _GLFW_HAS_GLXGETPROCADDRESS AND NOT _GLFW_HAS_GLXGETPROCADDRESSARB)
+ CHECK_FUNCTION_EXISTS(glXGetProcAddressEXT _GLFW_HAS_GLXGETPROCADDRESSEXT)
+ endif (NOT _GLFW_HAS_GLXGETPROCADDRESS AND NOT _GLFW_HAS_GLXGETPROCADDRESSARB)
+
+ if (NOT _GLFW_HAS_GLXGETPROCADDRESS AND
+ NOT _GLFW_HAS_GLXGETPROCADDRESSARB AND
+ NOT _GLFW_HAS_GLXGETPROCADDRESSEXT)
+ message(WARNING "No glXGetProcAddressXXX variant found")
+ endif (NOT _GLFW_HAS_GLXGETPROCADDRESS AND
+ NOT _GLFW_HAS_GLXGETPROCADDRESSARB AND
+ NOT _GLFW_HAS_GLXGETPROCADDRESSEXT)
+
+ # Select platform specific code
+ add_subdirectory(lib/x11)
+endif(UNIX AND NOT APPLE AND NOT CYGWIN)
+
+# Stuff specific to AGL and CGL on Mac OS X
+if (UNIX AND APPLE)
+ message(STATUS "Building GLFW for NSOpenGL on Mac OS X")
+
+ # Universal build, decent set of warning flags...
+ set(CMAKE_OSX_ARCHITECTURES ppc;i386;ppc64;x86_64)
+ set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.5.sdk)
+ set(CMAKE_C_FLAGS "-mmacosx-version-min=10.5 -Wall -Wextra -Wno-unused-parameter -Werror")
+
+ # Set up library and include paths
+ find_library(COCOA_FRAMEWORK Cocoa)
+ list(APPEND GLFW_LIBRARIES ${COCOA_FRAMEWORK})
+ list(APPEND GLFW_LIBRARIES ${OPENGL_gl_LIBRARY})
+
+ # Select platform specific code
+ add_subdirectory(lib/cocoa)
+endif(UNIX AND APPLE)
+
+add_subdirectory(examples)
+add_subdirectory(tests)
+#add_subdirectory(docs/doxygen)
+#add_subdirectory(docs/manuals)
+
+
+#--------------------------------------------------------------------
+# -- Install standard files
+#--------------------------------------------------------------------
+
+# Install the GLFW header file
+install(DIRECTORY include/ DESTINATION include
+ PATTERN ".svn" EXCLUDE
+ PATTERN "include/*"
+)
+
+# Install documentation
+install(
+ FILES
+ COPYING.txt
+ readme.html
+ DESTINATION
+ share/doc/glfw-${GLFW_VERSION_FULL}/
+)
+
+#--------------------------------------------------------------------
+# -- Additional stuff
+#--------------------------------------------------------------------
+
+#--------------------------------------------------------------------
+# -- Documentation generation
+#--------------------------------------------------------------------
+#include("${CMAKE_CURRENT_SOURCE_DIR}/documentation.cmake")
+#configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in"
+# "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile"
+# IMMEDIATE @ONLY)
+#add_doxygen_target("${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
+#add_subdirectory(docs)
+
+#--------------------------------------------------------------------
+# -- Uninstall operation
+# -------------------------------------------------------------------
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
+ IMMEDIATE @ONLY)
+add_custom_target(uninstall
+ "${CMAKE_COMMAND}" -P
+ "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
+
diff --git a/COPYING.txt b/COPYING.txt
new file mode 100644
index 00000000..0a69446d
--- /dev/null
+++ b/COPYING.txt
@@ -0,0 +1,21 @@
+Copyright (c) 2002-2007 Camilla Berglund
+
+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.
+
diff --git a/cmake_uninstall.cmake.in b/cmake_uninstall.cmake.in
new file mode 100644
index 00000000..17376d2e
--- /dev/null
+++ b/cmake_uninstall.cmake.in
@@ -0,0 +1,22 @@
+IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+ MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
+ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+
+FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+STRING(REGEX REPLACE "\n" ";" files "${files}")
+FOREACH(file ${files})
+ MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
+ IF(EXISTS "$ENV{DESTDIR}${file}")
+ EXEC_PROGRAM(
+ "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+ OUTPUT_VARIABLE rm_out
+ RETURN_VALUE rm_retval
+ )
+ IF(NOT "${rm_retval}" STREQUAL 0)
+ MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+ ENDIF(NOT "${rm_retval}" STREQUAL 0)
+ ELSE(EXISTS "$ENV{DESTDIR}${file}")
+ MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
+ ENDIF(EXISTS "$ENV{DESTDIR}${file}")
+ENDFOREACH(file)
+
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 00000000..6bc7da29
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,57 @@
+##########################################################################
+# Makefile for the GLFW documentation.
+##########################################################################
+
+PDFDOCS = glfwrm.pdf glfwug.pdf
+DVIDOCS = glfwrm.dvi glfwug.dvi
+
+
+##########################################################################
+# Build macros
+##########################################################################
+default: pdf
+pdf: $(PDFDOCS)
+dvi: $(DVIDOCS)
+
+
+##########################################################################
+# Clean macros
+##########################################################################
+clean:
+ rm -f glfwrm.dvi glfwrm.aux glfwrm.log glfwrm.out glfwrm.pdf glfwrm.toc glfwrm.lot
+ rm -f glfwug.dvi glfwug.aux glfwug.log glfwug.out glfwug.pdf glfwug.toc
+
+clean-win:
+ @.\\cleanup.bat
+
+
+##########################################################################
+# Rules for building the GLFW Reference Manual
+##########################################################################
+
+glfwrm.pdf: glfwrm.tex glfwrm.toc glfwrm.lot glfwdoc.sty
+ pdflatex glfwrm.tex
+
+glfwrm.dvi: glfwrm.tex glfwrm.toc glfwrm.lot glfwdoc.sty
+ latex glfwrm.tex
+
+glfwrm.toc: glfwrm.tex glfwdoc.sty
+ latex glfwrm.tex
+
+glfwrm.lot: glfwrm.tex glfwdoc.sty
+ latex glfwrm.tex
+
+
+##########################################################################
+# Rules for building the GLFW Users Guide
+##########################################################################
+
+glfwug.pdf: glfwug.tex glfwug.toc glfwdoc.sty
+ pdflatex glfwug.tex
+
+glfwug.dvi: glfwug.tex glfwug.toc glfwdoc.sty
+ latex glfwug.tex
+
+glfwug.toc: glfwug.tex glfwdoc.sty
+ latex glfwug.tex
+
diff --git a/docs/cleanup.bat b/docs/cleanup.bat
new file mode 100644
index 00000000..268a27b6
--- /dev/null
+++ b/docs/cleanup.bat
@@ -0,0 +1,22 @@
+@echo off
+
+REM ----------------------------------------------------------------------
+REM Windows cleanup batch file for the GLFW documentation.
+REM ----------------------------------------------------------------------
+
+REM GLFW Reference Manual
+if exist glfwrm.dvi del glfwrm.dvi
+if exist glfwrm.aux del glfwrm.aux
+if exist glfwrm.log del glfwrm.log
+if exist glfwrm.out del glfwrm.out
+if exist glfwrm.pdf del glfwrm.pdf
+if exist glfwrm.toc del glfwrm.toc
+if exist glfwrm.lot del glfwrm.lot
+
+REM GLFW Users Guide
+if exist glfwug.dvi del glfwug.dvi
+if exist glfwug.aux del glfwug.aux
+if exist glfwug.log del glfwug.log
+if exist glfwug.out del glfwug.out
+if exist glfwug.pdf del glfwug.pdf
+if exist glfwug.toc del glfwug.toc
diff --git a/docs/glfwdoc.sty b/docs/glfwdoc.sty
new file mode 100644
index 00000000..b7e7b97d
--- /dev/null
+++ b/docs/glfwdoc.sty
@@ -0,0 +1,80 @@
+%-------------------------------------------------------------------------
+% Common document formatting and macros for GLFW manuals
+%-------------------------------------------------------------------------
+
+% Misc. document info
+\date{\today}
+
+% Packages
+\usepackage{fancyhdr}
+\usepackage{titling}
+\usepackage{lastpage}
+\usepackage{listings}
+\usepackage{color}
+\usepackage[overload]{textcase}
+\usepackage{needspace}
+\usepackage{times}
+
+% Logo macros
+\newcommand{\OpenGL}[1][0]{\textbf{OpenGL}\texttrademark}
+\newcommand{\GLFW}[1][0]{\textbf{GLFW}}
+
+% Encoding
+\usepackage[latin1]{inputenc}
+\usepackage[T1]{fontenc}
+
+% Page formatting
+\usepackage[hmargin=2.5cm]{geometry}
+\raggedright
+\raggedbottom
+\sloppy
+\usepackage{parskip}
+
+% Header and footer
+\pagestyle{fancy}
+%\lhead{\textit{GLFW Reference Manual}}
+\lhead{\textit{GLFW \glfwdoctype}}
+\chead{API version \glfwapiver}
+\rhead{Page \thepage/\pageref{LastPage}}
+\lfoot{}
+\cfoot{}
+\rfoot{}
+\renewcommand{\headrulewidth}{0.4pt}
+\renewcommand{\footrulewidth}{0.0pt}
+
+% Titlepage
+\newcommand{\glfwmaketitle}{\begin{titlepage}\ \\%
+ \begin{center}%
+ \vspace{7.0cm}{\Huge\textbf{GLFW}}\\%
+ \rule{10.0cm}{0.5pt}\\%
+ \vspace{0.5cm}{\LARGE\textbf{\glfwdoctype}}\\%
+ \vspace{0.8cm}{\large\textbf{API version \glfwapiver}}\\%
+ \textit{\today}\\%
+ \vspace{1.5cm}\textbf{\textcopyright2002-2007 Camilla Berglund}\\%
+ \end{center}\end{titlepage}\newpage}
+
+% Colors
+\definecolor{code}{rgb}{0.9,0.9,1.0}
+\definecolor{link}{rgb}{0.6,0.0,0.0}
+\definecolor{codeA}{rgb}{0.9,1.0,0.9}
+\definecolor{codeB}{rgb}{1.0,0.9,0.9}
+
+% Code listings
+\lstset{frame=single,frameround=tttt,backgroundcolor=\color{code},%
+ language=C,basicstyle={\ttfamily},%
+ breaklines,breakindent=0pt,postbreak=\space\space\space\space}
+
+
+% A simple hack for keeping lines together
+\newenvironment{mysamepage}[1][2]{\begin{samepage}\needspace{#1\baselineskip}}{\end{samepage}}
+
+% Macros for automating function reference entries
+\newenvironment{refparameters}[1][0]{\begin{mysamepage}\textbf{Parameters}\\}{\end{mysamepage}\bigskip}
+\newenvironment{refreturn}[1][0]{\begin{mysamepage}\textbf{Return values}\\}{\end{mysamepage}\bigskip}
+\newenvironment{refdescription}[1][0]{\begin{mysamepage}\textbf{Description}\\}{\end{mysamepage}\bigskip}
+\newenvironment{refnotes}[1][0]{\begin{mysamepage}\textbf{Notes}\\}{\end{mysamepage}\bigskip}
+
+% hyperref (bookmarks, links etc) - use this package last
+\usepackage[colorlinks=true,linkcolor=link,bookmarks=true,bookmarksopen=true,%
+ pdfhighlight=/N,bookmarksnumbered=true,bookmarksopenlevel=1,%
+ pdfview=FitH,pdfstartview=FitH]{hyperref}
diff --git a/docs/glfwrm.tex b/docs/glfwrm.tex
new file mode 100644
index 00000000..72f87934
--- /dev/null
+++ b/docs/glfwrm.tex
@@ -0,0 +1,2128 @@
+%-------------------------------------------------------------------------
+% GLFW Reference Manual
+% API Version: 2.7
+%-------------------------------------------------------------------------
+
+% Document class
+\documentclass[a4paper,11pt,oneside]{report}
+
+% Document title and API version
+\newcommand{\glfwdoctype}[1][0]{Reference Manual}
+\newcommand{\glfwapiver}[1][0]{2.7}
+
+% Common document settings and macros
+\input{glfwdoc.sty}
+
+% PDF specific document settings
+\hypersetup{pdftitle={GLFW Reference Manual}}
+\hypersetup{pdfauthor={Marcus Geelnard}}
+\hypersetup{pdfkeywords={GLFW,OpenGL,reference,manual}}
+
+
+%-------------------------------------------------------------------------
+% Document body
+%-------------------------------------------------------------------------
+
+\begin{document}
+
+\pagestyle{plain}
+
+% Title page
+\glfwmaketitle
+
+% Summary, trademarks and table of contents
+\pagenumbering{roman}
+\setcounter{page}{1}
+
+%-------------------------------------------------------------------------
+% Summary and Trademarks
+%-------------------------------------------------------------------------
+\chapter*{Summary}
+
+This document is primarily a function reference manual for the \GLFW\ API.
+For a description of how to use \GLFW\ you should refer to the
+\textit{GLFW Users Guide}.
+\vspace{10cm}
+
+\large
+Trademarks
+
+\small
+OpenGL and IRIX are registered trademarks of Silicon Graphics, Inc.\linebreak
+Microsoft and Windows are registered trademarks of Microsoft Corporation.\linebreak
+Mac OS is a registered trademark of Apple Computer, Inc.\linebreak
+Linux is a registered trademark of Linus Torvalds.\linebreak
+FreeBSD is a registered trademark of Wind River Systems, Inc.\linebreak
+Solaris is a trademark of Sun Microsystems, Inc.\linebreak
+UNIX is a registered trademark of The Open Group.\linebreak
+X Window System is a trademark of The Open Group.\linebreak
+POSIX is a trademark of IEEE.\linebreak
+Truevision, TARGA and TGA are registered trademarks of Truevision, Inc.\linebreak
+
+All other trademarks mentioned in this document are the property of their respective owners.
+\normalsize
+
+
+%-------------------------------------------------------------------------
+% Table of contents
+%-------------------------------------------------------------------------
+\tableofcontents
+
+%-------------------------------------------------------------------------
+% List of tables
+%-------------------------------------------------------------------------
+\listoftables
+\pagebreak
+
+
+% Document chapters starts here...
+\pagenumbering{arabic}
+\setcounter{page}{1}
+
+\pagestyle{fancy}
+
+
+%-------------------------------------------------------------------------
+% Introduction
+%-------------------------------------------------------------------------
+\chapter{Introduction}
+\thispagestyle{fancy}
+
+\GLFW\ is a portable API (Application Program Interface) that handles
+operating system specific tasks related to \OpenGL\ programming. While
+\OpenGL\ in general is portable, easy to use and often results in tidy and
+compact code, the operating system specific mechanisms that are required
+to set up and manage an \OpenGL\ window are quite the opposite. \GLFW\ tries
+to remedy this by providing the following functionality:
+
+\begin{itemize}
+\item Opening and managing an \OpenGL\ window.
+\item Keyboard, mouse and joystick input.
+\item A high precision timer.
+\item Support for querying and using \OpenGL\ extensions.
+\end{itemize}
+\vspace{18pt}
+
+All this functionality is implemented as a set of easy-to-use functions,
+which makes it possible to write an \OpenGL\ application framework in just a
+few lines of code. The \GLFW\ API is completely operating system and
+platform independent, which makes it very simple to port \GLFW\ based \OpenGL\
+applications to a variety of platforms.
+
+Currently supported platforms are:
+\begin{itemize}
+\item Microsoft Windows\textsuperscript{\textregistered} 95/98/ME/NT/2000/XP/Vista.
+\item Unix\textsuperscript{\textregistered} or Unix-like systems running the
+X Window System\texttrademark, e.g. Linux\textsuperscript{\textregistered},
+IRIX\textsuperscript{\textregistered}, FreeBSD\textsuperscript{\textregistered},
+Solaris\texttrademark, QNX\textsuperscript{\textregistered} and
+Mac OS\textsuperscript{\textregistered} X.
+\item Mac OS\textsuperscript{\textregistered} X (Carbon)\footnote{Support for joysticks missing at the time of writing.}
+\end{itemize}
+
+
+
+%-------------------------------------------------------------------------
+% GLFW Operation
+%-------------------------------------------------------------------------
+\chapter{GLFW Operation Overview}
+\thispagestyle{fancy}
+
+
+%-------------------------------------------------------------------------
+\section{The GLFW Window}
+\GLFW\ only supports one opened window at a time. The window can be either
+a normal desktop window or a fullscreen window. The latter is completely
+undecorated, without window borders, and covers the entire monitor. With
+a fullscreen window, it is also possible to select which video mode to use.
+
+When a window is opened, an \OpenGL\ rendering context is created and
+attached to the entire client area of the window. When the window is closed,
+the \OpenGL\ rendering context is detached and destroyed.
+
+Through a window it is possible to receive user input in the form of
+keyboard and mouse input. User input is exposed through the \GLFW\ API via
+callback functions. There are different callback functions for dealing with
+different kinds of user input. Also, \GLFW\ stores most user input as
+internal state that can be queried through different \GLFW\ API functions
+(for instance it is possible to query the position of the mouse cursor
+with the \textbf{glfwGetMousePos} function).
+
+As for user input, it is possible to receive information about window
+state changes, such as window resize or close events, through callback
+functions. It is also possible to query different kinds of window
+information through different \GLFW\ API functions.
+
+
+%-------------------------------------------------------------------------
+\section{The GLFW Event Loop}
+The \GLFW\ event loop is an open loop, which means that it is up to the
+programmer to design the loop. Events are processed by calling specific
+\GLFW\ functions, which in turn query the system for new input and window
+events, and reports these events back to the program through callback
+functions.
+
+The programmer decides when to call the event processing functions, and
+when to abort the event loop.
+
+In pseudo language, a typical event loop might look like this:
+
+\begin{lstlisting}
+ repeat until window is closed
+ {
+ poll events
+ draw OpenGL graphics
+ }
+\end{lstlisting}
+
+There are two ways to handle events in \GLFW :
+
+\begin{itemize}
+ \item Block the event loop while waiting for new events.
+ \item Poll for new events, and continue the loop regardless if there are
+ any new events or not.
+\end{itemize}
+
+The first method is useful for interactive applications that do not
+need to refresh the \OpenGL\ display unless the user interacts with the
+application through user input. Typical applications are CAD software
+and other kinds of editors.
+
+The second method is useful for applications that need to refresh the
+\OpenGL\ display constantly, regardless of user input, such as games,
+demos, 3D animations, screen savers and so on.
+
+
+%-------------------------------------------------------------------------
+\section{Callback Functions}
+Using callback functions can be a good method for receiving up to date
+information about window state and user input. When a window has been
+opened, it is possible to register custom callback functions that will
+be called when certain events occur.
+
+Callback functions are called from any of the event polling functions
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers}.
+
+Callback functions should \emph{only} be used to gather information. Since
+the callback functions are called from within the internal \GLFW\ event
+polling loops, they should not call any \GLFW\ functions that might
+result in considerable \GLFW\ state changes, nor stall the event polling
+loop for a lengthy period of time.
+
+In other words, most or all \OpenGL\ rendering should be called from the
+main application event loop, not from any of the \GLFW\ callback
+functions. Also, the only \GLFW\ functions that may be safely called from
+callback functions are the different Get functions (e.g.
+\textbf{glfwGetKey}, \textbf{glfwGetTime}, \textbf{glfwGetWindowParam}
+etc).
+
+
+%-------------------------------------------------------------------------
+% Function Reference
+%-------------------------------------------------------------------------
+\chapter{Function Reference}
+\thispagestyle{fancy}
+
+%-------------------------------------------------------------------------
+\section{GLFW Initialization and Termination}
+Before any \GLFW\ functions can be used, \GLFW\ must be initialized to
+ensure proper functionality, and before a program terminates, \GLFW\ has to
+be terminated in order to free up resources etc.
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwInit}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+int glfwInit( void )
+\end{lstlisting}
+
+\begin{refparameters}
+none
+\end{refparameters}
+
+\begin{refreturn}
+If the function succeeds, GL\_TRUE is returned.\\
+If the function fails, GL\_FALSE is returned.
+\end{refreturn}
+
+\begin{refdescription}
+The glfwInit function initializes \GLFW. No other \GLFW\ functions may be
+used before this function has been called.
+\end{refdescription}
+
+\begin{refnotes}
+This function may take several seconds to complete on some systems, while
+on other systems it may take only a fraction of a second to complete.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwTerminate}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwTerminate( void )
+\end{lstlisting}
+
+\begin{refparameters}
+none
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function terminates \GLFW. Among other things it closes the window,
+if it is opened. This function must be called before a program exits.
+\end{refdescription}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetVersion}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwGetVersion( int *major, int *minor, int *rev )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{major}]\ \\
+ Pointer to an integer that will hold the major version number.
+\item [\textit{minor}]\ \\
+ Pointer to an integer that will hold the minor version number.
+\item [\textit{rev}]\ \\
+ Pointer to an integer that will hold the revision.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The function returns the major and minor version numbers and the revision
+for the currently linked \GLFW\ library.
+\end{refreturn}
+
+\begin{refdescription}
+The function returns the \GLFW\ library version.
+\end{refdescription}
+
+
+%-------------------------------------------------------------------------
+\pagebreak
+\section{Window Handling}
+The main functionality of \GLFW\ is to provide a simple interface to
+\OpenGL\ window management. \GLFW\ can open one window, which can be
+either a normal desktop window or a fullscreen window.
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwOpenWindow}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+int glfwOpenWindow( int width, int height, int redbits,
+ int greenbits, int bluebits, int alphabits, int depthbits,
+ int stencilbits, int mode )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{width}]\ \\
+ The width of the window. If \textit{width} is zero, it will be
+ calculated as ${width=\frac{4}{3}height}$, if \textit{height} is not
+ zero. If both \textit{width} and \textit{height} are zero, then
+ \textit{width} will be set to 640.
+\item [\textit{height}]\ \\
+ The height of the window. If \textit{height} is zero, it will be
+ calculated as ${height=\frac{3}{4}width}$, if \textit{width} is not
+ zero. If both \textit{width} and \textit{height} are zero, then
+ \textit{height} will be set to 480.
+\item [\textit{redbits, greenbits, bluebits}]\ \\
+ The number of bits to use for each color component of the color buffer
+ (0 means default color depth). For instance, setting \textit{redbits=5,
+ greenbits=6, and bluebits=5} will generate a 16-bit color buffer, if
+ possible.
+\item [\textit{alphabits}]\ \\
+ The number of bits to use for the alpha buffer (0 means no alpha
+ buffer).
+\item [\textit{depthbits}]\ \\
+ The number of bits to use for the depth buffer (0 means no depth
+ buffer).
+\item [\textit{stencilbits}]\ \\
+ The number of bits to use for the stencil buffer (0 means no stencil
+ buffer).
+\item [\textit{mode}]\ \\
+ Selects which type of \OpenGL\ window to use. \textit{mode} can be
+ either GLFW\_WINDOW, which will generate a normal desktop window, or
+ GLFW\_FULLSCREEN, which will generate a window which covers the entire
+ screen. When GLFW\_FULLSCREEN is selected, the video mode will be
+ changed to the resolution that closest matches the \textit{width} and
+ \textit{height} parameters.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+If the function succeeds, GL\_TRUE is returned.\\
+If the function fails, GL\_FALSE is returned.
+\end{refreturn}
+
+\begin{refdescription}
+The function opens a window that best matches the parameters given to the
+function. How well the resulting window matches the desired window depends
+mostly on the available hardware and \OpenGL\ drivers. In general,
+selecting a fullscreen mode has better chances of generating a close match
+than does a normal desktop window, since \GLFW\ can freely select from all
+the available video modes. A desktop window is normally restricted to the
+video mode of the desktop.
+\end{refdescription}
+
+\begin{refnotes}
+For additional control of window properties, see
+\textbf{glfwOpenWindowHint}.
+
+In fullscreen mode the mouse cursor is hidden by default, and any system
+screensavers are prohibited from starting. In windowed mode the mouse
+cursor is visible, and screensavers are allowed to start. To change the
+visibility of the mouse cursor, use \textbf{glfwEnable} or
+\textbf{glfwDisable} with the argument GLFW\_MOUSE\_CURSOR.
+
+In order to determine the actual properties of an opened window, use
+\textbf{glfwGetWindowParam} and \textbf{glfwGetWindowSize} (or
+\textbf{glfwSetWindowSizeCallback}).
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\begin{table}[p]
+\begin{center}
+\begin{tabular}{|l|l|p{7.0cm}|} \hline \raggedright
+\textbf{Name} & \textbf{Default} & \textbf{Description} \\ \hline
+GLFW\_REFRESH\_RATE & 0 & Vertical monitor refresh rate in Hz (only used for fullscreen windows). Zero means system default.\\ \hline
+GLFW\_ACCUM\_RED\_BITS & 0 & Number of bits for the red channel of the accumulator buffer.\\ \hline
+GLFW\_ACCUM\_GREEN\_BITS & 0 & Number of bits for the green channel of the accumulator buffer.\\ \hline
+GLFW\_ACCUM\_BLUE\_BITS & 0 & Number of bits for the blue channel of the accumulator buffer.\\ \hline
+GLFW\_ACCUM\_ALPHA\_BITS & 0 & Number of bits for the alpha channel of the accumulator buffer.\\ \hline
+GLFW\_AUX\_BUFFERS & 0 & Number of auxiliary buffers.\\ \hline
+GLFW\_STEREO & GL\_FALSE & Specify if stereo rendering should be supported (can be GL\_TRUE or GL\_FALSE).\\ \hline
+GLFW\_WINDOW\_NO\_RESIZE & GL\_FALSE & Specify whether the window can be resized (not used for fullscreen windows).\\ \hline
+GLFW\_FSAA\_SAMPLES & 0 & Number of samples to use for the multisampling buffer. Zero disables multisampling.\\ \hline
+GLFW\_OPENGL\_VERSION\_MAJOR & 0 & Major number of the desired OpenGL version.
+ The default requests the highest OpenGL version equal to or lower than 2.1.\\ \hline
+GLFW\_OPENGL\_VERSION\_MINOR & 0 & Minor number of the desired OpenGL version.
+ The default requests the highest OpenGL version equal to or lower than 2.1.\\ \hline
+GLFW\_OPENGL\_FORWARD\_COMPAT & GL\_FALSE & Specify whether the OpenGL context should be forward compatible (i.e. disallow legacy functionality).
+ This hint is ignored for OpenGL version 2.1 and below.\\ \hline
+\end{tabular}
+\end{center}
+\caption{Targets for \textbf{glfwOpenWindowHint}}
+\label{tab:winhints}
+\end{table}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwOpenWindowHint}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwOpenWindowHint( int target, int hint )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{target}]\ \\
+ Can be any of the constants in the table \ref{tab:winhints}.
+\item [\textit{hint}]\ \\
+ An integer giving the value of the corresponding target (see table
+ \ref{tab:winhints}).
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function sets additional properties for a window that is to be opened.
+For a hint to be registered, the function must be called before calling
+\textbf{glfwOpenWindow}. When the \textbf{glfwOpenWindow} function is
+called, any hints that were registered with the \textbf{glfwOpenWindowHint}
+function are used for setting the corresponding window properties, and
+then all hints are reset to their default values.
+\end{refdescription}
+
+\begin{refnotes}
+In order to determine the actual properties of an opened window, use
+\textbf{glfwGetWindowParam} (after the window has been opened).
+
+GLFW\_STEREO is a hard constraint. If stereo rendering is requested, but
+no stereo rendering capable pixel formats / visuals are available,
+\textbf{glfwOpenWindow} will fail.
+
+The GLFW\_REFRESH\_RATE property should be used with caution. Most
+systems have default values for monitor refresh rates that are optimal
+for the specific system. Specifying the refresh rate can override these
+settings, which can result in suboptimal operation. The monitor may be
+unable to display the resulting video signal, or in the worst case it may
+even be damaged!
+
+If you want to create a context with OpenGL version 3.0 or above you have to
+set the GLFW\_OPENGL\_VERSION\_MAJOR and GLFW\_OPENGL\_VERSION\_MINOR hints
+accordingly. If you don't do this, the highest OpenGL version available for a
+context is 2.1 or lower.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwCloseWindow}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwCloseWindow( void )
+\end{lstlisting}
+
+\begin{refparameters}
+none
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function closes an opened window and destroys the associated \OpenGL\
+context.
+\end{refdescription}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetWindowCloseCallback}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetWindowCloseCallback( GLFWwindowclosefun cbfun )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{cbfun}]\ \\
+ Pointer to a callback function that will be called when a user requests
+ that the window should be closed, typically by clicking the window close
+ icon (e.g. the cross in the upper right corner of a window under
+ Microsoft Windows). The function should have the following C language
+ prototype:
+
+ \texttt{int GLFWCALL functionname( void );}
+
+ Where \textit{functionname} is the name of the callback function. The
+ return value of the callback function indicates wether or not the window
+ close action should continue. If the function returns GL\_TRUE, the
+ window will be closed. If the function returns GL\_FALSE, the window
+ will not be closed.
+
+ If \textit{cbfun} is NULL, any previously selected callback function
+ will be deselected.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function selects which function to be called upon a window close
+event.
+
+A window has to be opened for this function to have any effect.
+\end{refdescription}
+
+\begin{refnotes}
+Window close events are recorded continuously, but only reported when
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers} is called.
+
+The \OpenGL\ context is still valid when this function is called.
+
+Note that the window close callback function is not called when
+\textbf{glfwCloseWindow} is called, but only when the close request
+comes from the window manager.
+
+Do \emph{not} call \textbf{glfwCloseWindow} from a window close
+callback function. Close the window by returning GL\_TRUE from the
+function.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetWindowTitle}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetWindowTitle( const char *title )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{title}]\ \\
+ Pointer to a null terminated ISO~8859-1 (8-bit Latin~1) string that
+ holds the title of the window.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function changes the title of the opened window.
+\end{refdescription}
+
+\begin{refnotes}
+The title property of a window is often used in situations other than for
+the window title, such as the title of an application icon when it is in
+iconified state.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetWindowSize}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetWindowSize( int width, int height )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{width}]\ \\
+ Width of the window.
+\item [\textit{height}]\ \\
+ Height of the window.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function changes the size of an opened window. The \textit{width} and
+\textit{height} parameters denote the size of the client area of the
+window (i.e. excluding any window borders and decorations).
+
+If the window is in fullscreen mode, the video mode will be changed to a
+resolution that closest matches the width and height parameters (the
+number of color bits will not be changed).
+\end{refdescription}
+
+\begin{refnotes}
+The \OpenGL\ context is guaranteed to be preserved after calling
+\textbf{glfwSetWindowSize}, even if the video mode is changed.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetWindowPos}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetWindowPos( int x, int y )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{x}]\ \\
+ Horizontal position of the window, relative to the upper left corner
+ of the desktop.
+\item [\textit{y}]\ \\
+ Vertical position of the window, relative to the upper left corner of
+ the desktop.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function changes the position of an opened window. It does not have
+any effect on a fullscreen window.
+\end{refdescription}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetWindowSize}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwGetWindowSize( int *width, int *height )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{width}]\ \\
+ Pointer to an integer that will hold the width of the window.
+\item [\textit{height}]\ \\
+ Pointer to an integer that will hold the height of the window.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The current width and height of the opened window is returned in the
+\textit{width} and \textit{height} parameters, respectively.
+\end{refreturn}
+
+\begin{refdescription}
+The function is used for determining the size of an opened window.
+The returned values are dimensions of the client area of the window
+(i.e. excluding any window borders and decorations).
+\end{refdescription}
+
+\begin{refnotes}
+Even if the size of a fullscreen window does not change once the window
+has been opened, it does not necessarily have to be the same as the size
+that was requested using \textbf{glfwOpenWindow}. Therefor it is wise to
+use this function to determine the true size of the window once it has
+been opened.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetWindowSizeCallback}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetWindowSizeCallback( GLFWwindowsizefun cbfun )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{cbfun}]\ \\
+ Pointer to a callback function that will be called every time the
+ window size changes. The function should have the following C language
+ prototype:
+
+ \texttt{void GLFWCALL functionname( int width, int height );}
+
+ Where \textit{functionname} is the name of the callback function, and
+ \textit{width} and \textit{height} are the dimensions of the window
+ client area.
+
+ If \textit{cbfun} is NULL, any previously selected callback function
+ will be deselected.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function selects which function to be called upon a window size
+change event.
+
+A window has to be opened for this function to have any effect.
+\end{refdescription}
+
+\begin{refnotes}
+Window size changes are recorded continuously, but only reported when
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers} is called.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwIconifyWindow}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwIconifyWindow( void )
+\end{lstlisting}
+
+\begin{refparameters}
+none
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+Iconify a window. If the window is in fullscreen mode, then the desktop
+video mode will be restored.
+\end{refdescription}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwRestoreWindow}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwRestoreWindow( void )
+\end{lstlisting}
+
+\begin{refparameters}
+none
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+Restore an iconified window. If the window that is restored is in
+fullscreen mode, then the fullscreen video mode will be restored.
+\end{refdescription}
+
+
+%-------------------------------------------------------------------------
+\begin{table}[p]
+\begin{center}
+\begin{tabular}{|l|p{9.5cm}|} \hline \raggedright
+\textbf{Name} & \textbf{Description} \\ \hline
+GLFW\_OPENED & GL\_TRUE if window is opened, else GL\_FALSE.\\ \hline
+GLFW\_ACTIVE & GL\_TRUE if window has focus, else GL\_FALSE.\\ \hline
+GLFW\_ICONIFIED & GL\_TRUE if window is iconified, else GL\_FALSE.\\ \hline
+GLFW\_ACCELERATED & GL\_TRUE if window is hardware accelerated, else GL\_FALSE.\\ \hline
+GLFW\_RED\_BITS & Number of bits for the red color component.\\ \hline
+GLFW\_GREEN\_BITS & Number of bits for the green color component.\\ \hline
+GLFW\_BLUE\_BITS & Number of bits for the blue color component.\\ \hline
+GLFW\_ALPHA\_BITS & Number of bits for the alpha buffer.\\ \hline
+GLFW\_DEPTH\_BITS & Number of bits for the depth buffer.\\ \hline
+GLFW\_STENCIL\_BITS & Number of bits for the stencil buffer.\\ \hline
+GLFW\_REFRESH\_RATE & Vertical monitor refresh rate in Hz. Zero indicates an unknown or a default refresh rate.\\ \hline
+GLFW\_ACCUM\_RED\_BITS & Number of bits for the red channel of the accumulator buffer.\\ \hline
+GLFW\_ACCUM\_GREEN\_BITS & Number of bits for the green channel of the accumulator buffer.\\ \hline
+GLFW\_ACCUM\_BLUE\_BITS & Number of bits for the blue channel of the accumulator buffer.\\ \hline
+GLFW\_ACCUM\_ALPHA\_BITS & Number of bits for the alpha channel of the accumulator buffer.\\ \hline
+GLFW\_AUX\_BUFFERS & Number of auxiliary buffers.\\ \hline
+GLFW\_STEREO & GL\_TRUE if stereo rendering is supported, else GL\_FALSE.\\ \hline
+GLFW\_WINDOW\_NO\_RESIZE & GL\_TRUE if the window cannot be resized, else GL\_FALSE.\\ \hline
+GLFW\_FSAA\_SAMPLES & Number of multisampling buffer samples. Zero indicated multisampling is disabled.\\ \hline
+GLFW\_OPENGL\_VERSION\_MAJOR & Major number of the desired OpenGL version.\\ \hline
+GLFW\_OPENGL\_VERSION\_MINOR & Minor number of the desired OpenGL version.\\ \hline
+GLFW\_OPENGL\_FORWARD\_COMPAT & GL\_TRUE if the OpenGL context is forward compatible (i.e. disallows legacy functionality), else GL\_FALSE.
+This is always GL\_FALSE for OpenGL version 2.1 and below.\\ \hline
+\end{tabular}
+\end{center}
+\caption{Window parameters for \textbf{glfwGetWindowParam}}
+\label{tab:winparams}
+\end{table}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetWindowParam}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+int glfwGetWindowParam( int param )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{param}]\ \\
+ A token selecting which parameter the function should return (see
+ table \ref{tab:winparams}).
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The function returns different parameters depending on the value of
+\textit{param}. Table \ref{tab:winparams} lists valid \textit{param}
+values, and their corresponding return values.
+\end{refreturn}
+
+\begin{refdescription}
+The function is used for acquiring various properties of an opened window.
+\end{refdescription}
+
+\begin{refnotes}
+GLFW\_ACCELERATED is only supported under Windows. Other systems will
+always return GL\_TRUE. Under Windows, GLFW\_ACCELERATED means that the
+\OpenGL\ renderer is a 3rd party renderer, rather than the fallback
+Microsoft software \OpenGL\ renderer. In other words, it is not a real
+guarantee that the \OpenGL\ renderer is actually hardware accelerated.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSwapBuffers}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSwapBuffers( void )
+\end{lstlisting}
+
+\begin{refparameters}
+none
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function swaps the back and front color buffers of the window. If
+GLFW\_AUTO\_POLL\_EVENTS is enabled (which is the default),
+\textbf{glfwPollEvents} is called before swapping the front and back
+buffers.
+\end{refdescription}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSwapInterval}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSwapInterval( int interval )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{interval}]\ \\
+ Minimum number of monitor vertical retraces between each buffer swap
+ performed by \textbf{glfwSwapBuffers}. If \textit{interval} is zero,
+ buffer swaps will not be synchronized to the vertical refresh of the
+ monitor (also known as 'VSync off').
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function selects the minimum number of monitor vertical retraces that
+should occur between two buffer swaps. If the selected swap interval is
+one, the rate of buffer swaps will never be higher than the vertical
+refresh rate of the monitor. If the selected swap interval is zero, the
+rate of buffer swaps is only limited by the speed of the software and
+the hardware.
+\end{refdescription}
+
+\begin{refnotes}
+This function will only have an effect on hardware and drivers that
+support user selection of the swap interval.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetWindowRefreshCallback}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetWindowRefreshCallback( GLFWwindowrefreshfun cbfun )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{cbfun}]\ \\
+ Pointer to a callback function that will be called when the window client
+ area needs to be refreshed. The function should have the following C
+ language prototype:
+
+ \texttt{void GLFWCALL functionname( void );}
+
+ Where \textit{functionname} is the name of the callback function.
+
+ If \textit{cbfun} is NULL, any previously selected callback function
+ will be deselected.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function selects which function to be called upon a window refresh
+event, which occurs when any part of the window client area has been
+damaged, and needs to be repainted (for instance, if a part of the window
+that was previously occluded by another window has become visible).
+
+A window has to be opened for this function to have any effect.
+\end{refdescription}
+
+\begin{refnotes}
+Window refresh events are recorded continuously, but only reported when
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers} is called.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\pagebreak
+\section{Video Modes}
+Since \GLFW\ supports video mode changes when using a fullscreen window,
+it also provides functionality for querying which video modes are
+supported on a system.
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetVideoModes}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+int glfwGetVideoModes( GLFWvidmode *list, int maxcount )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{list}]\ \\
+ A vector of \textit{GLFWvidmode} structures, which will be filled out
+ by the function.
+\item [\textit{maxcount}]\ \\
+ Maximum number of video modes that \textit{list} vector can hold.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The function returns the number of detected video modes (this number
+will never exceed \textit{maxcount}). The \textit{list} vector is
+filled out with the video modes that are supported by the system.
+\end{refreturn}
+
+\begin{refdescription}
+The function returns a list of supported video modes. Each video mode is
+represented by a \textit{GLFWvidmode} structure, which has the following
+definition:
+
+\begin{lstlisting}
+typedef struct {
+ int Width, Height; // Video resolution
+ int RedBits; // Number of red bits
+ int GreenBits; // Number of green bits
+ int BlueBits; // Number of blue bits
+} GLFWvidmode;
+\end{lstlisting}
+\end{refdescription}
+
+\begin{refnotes}
+The returned list is sorted, first by color depth ($RedBits + GreenBits +
+BlueBits$), and then by resolution ($Width \times Height$), with the
+lowest resolution, fewest bits per pixel mode first.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetDesktopMode}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwGetDesktopMode( GLFWvidmode *mode )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{mode}]\ \\
+ Pointer to a \textit{GLFWvidmode} structure, which will be filled out
+ by the function.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The \textit{GLFWvidmode} structure pointed to by \textit{mode} is filled
+out with the desktop video mode.
+\end{refreturn}
+
+\begin{refdescription}
+The function returns the desktop video mode in a \textit{GLFWvidmode}
+structure. See \textbf{glfwGetVideoModes} for a definition of the
+\textit{GLFWvidmode} structure.
+\end{refdescription}
+
+\begin{refnotes}
+The color depth of the desktop display is always reported as the number
+of bits for each individual color component (red, green and blue), even
+if the desktop is not using an RGB or RGBA color format. For instance, an
+indexed 256 color display may report \textit{RedBits} = 3,
+\textit{GreenBits} = 3 and \textit{BlueBits} = 2, which adds up to 8 bits
+in total.
+
+The desktop video mode is the video mode used by the desktop, \textit{not}
+the current video mode (which may differ from the desktop video mode if
+the \GLFW\ window is a fullscreen window).
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\pagebreak
+\section{Input Handling}
+\GLFW\ supports three channels of user input: keyboard input, mouse input
+and joystick input.
+
+Keyboard and mouse input can be treated either as events, using callback
+functions, or as state, using functions for polling specific keyboard and
+mouse states. Regardless of which method is used, all keyboard and mouse
+input is collected using window event polling.
+
+Joystick input is asynchronous to the keyboard and mouse input, and does
+not require event polling for keeping up to date joystick information.
+Also, joystick input is independent of any window, so a window does not
+have to be opened for joystick input to be used.
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwPollEvents}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwPollEvents( void )
+\end{lstlisting}
+
+\begin{refparameters}
+none
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function is used for polling for events, such as user input and
+window resize events. Upon calling this function, all window states,
+keyboard states and mouse states are updated. If any related callback
+functions are registered, these are called during the call to
+\textbf{glfwPollEvents}.
+\end{refdescription}
+
+\begin{refnotes}
+\textbf{glfwPollEvents} is called implicitly from \textbf{glfwSwapBuffers}
+if GLFW\_AUTO\_POLL\_EVENTS is enabled (default). Thus, if
+\textbf{glfwSwapBuffers} is called frequently, which is normally the case,
+there is no need to call \textbf{glfwPollEvents}.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwWaitEvents}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwWaitEvents( void )
+\end{lstlisting}
+
+\begin{refparameters}
+none
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function is used for waiting for events, such as user input and
+window resize events. Upon calling this function, the calling thread will
+be put to sleep until any event appears in the event queue. When events
+are ready, the events will be processed just as they are processed by
+\textbf{glfwPollEvents}.
+
+If there are any events in the queue when the function is called, the
+function will behave exactly like \textbf{glfwPollEvents} (i.e. process
+all messages and then return, without blocking the calling thread).
+\end{refdescription}
+
+\begin{refnotes}
+It is guaranteed that \textbf{glfwWaitEvents} will wake up on any event
+that can be processed by \textbf{glfwPollEvents}. However,
+\textbf{glfwWaitEvents} may wake up on events that are \emph{not}
+processed or reported by \textbf{glfwPollEvents} too, and the function
+may behave differently on different systems. Do not make any assumptions
+about when or why \textbf{glfwWaitEvents} will return.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\begin{table}[p]
+\begin{center}
+\begin{tabular}{|l|l|} \hline \raggedright
+\textbf{Name} & \textbf{Description} \\ \hline
+GLFW\_KEY\_SPACE & Space\\ \hline
+GLFW\_KEY\_ESC & Escape\\ \hline
+GLFW\_KEY\_F\textit{n} & Function key \textit{n} (\textit{n} can be in the range 1..25)\\ \hline
+GLFW\_KEY\_UP & Cursor up\\ \hline
+GLFW\_KEY\_DOWN & Cursor down\\ \hline
+GLFW\_KEY\_LEFT & Cursor left\\ \hline
+GLFW\_KEY\_RIGHT & Cursor right\\ \hline
+GLFW\_KEY\_LSHIFT & Left shift key\\ \hline
+GLFW\_KEY\_RSHIFT & Right shift key\\ \hline
+GLFW\_KEY\_LCTRL & Left control key\\ \hline
+GLFW\_KEY\_RCTRL & Right control key\\ \hline
+GLFW\_KEY\_LALT & Left alternate function key\\ \hline
+GLFW\_KEY\_RALT & Right alternate function key\\ \hline
+GLFW\_KEY\_TAB & Tabulator\\ \hline
+GLFW\_KEY\_ENTER & Enter\\ \hline
+GLFW\_KEY\_BACKSPACE & Backspace\\ \hline
+GLFW\_KEY\_INSERT & Insert\\ \hline
+GLFW\_KEY\_DEL & Delete\\ \hline
+GLFW\_KEY\_PAGEUP & Page up\\ \hline
+GLFW\_KEY\_PAGEDOWN & Page down\\ \hline
+GLFW\_KEY\_HOME & Home\\ \hline
+GLFW\_KEY\_END & End\\ \hline
+GLFW\_KEY\_KP\_\textit{n} & Keypad numeric key \textit{n} (\textit{n} can be in the range 0..9)\\ \hline
+GLFW\_KEY\_KP\_DIVIDE & Keypad divide ($\div$)\\ \hline
+GLFW\_KEY\_KP\_MULTIPLY & Keypad multiply ($\times$)\\ \hline
+GLFW\_KEY\_KP\_SUBTRACT & Keypad subtract ($-$)\\ \hline
+GLFW\_KEY\_KP\_ADD & Keypad add ($+$)\\ \hline
+GLFW\_KEY\_KP\_DECIMAL & Keypad decimal (. or ,)\\ \hline
+GLFW\_KEY\_KP\_EQUAL & Keypad equal (=)\\ \hline
+GLFW\_KEY\_KP\_ENTER & Keypad enter\\ \hline
+\end{tabular}
+\end{center}
+\caption{Special key identifiers}
+\label{tab:keys}
+\end{table}
+
+
+%-------------------------------------------------------------------------
+\begin{table}[p]
+\begin{center}
+\begin{tabular}{|l|l|} \hline \raggedright
+\textbf{Name} & \textbf{Description} \\ \hline
+GLFW\_MOUSE\_BUTTON\_LEFT & Left mouse button (button 1) \\ \hline
+GLFW\_MOUSE\_BUTTON\_RIGHT & Right mouse button (button 2) \\ \hline
+GLFW\_MOUSE\_BUTTON\_MIDDLE & Middle mouse button (button 3) \\ \hline
+GLFW\_MOUSE\_BUTTON\_\textit{n} & Mouse button \textit{n} (\textit{n} can be in the range 1..8)\\ \hline
+\end{tabular}
+\end{center}
+\caption{Valid mouse button identifiers}
+\label{tab:mousebuttons}
+\end{table}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetKey}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+int glfwGetKey( int key )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{key}]\ \\
+ A keyboard key identifier, which can be either an uppercase printable
+ ISO~8859-1 (Latin~1) character (e.g. 'A', '3' or '.'), or a special key
+ identifier. Table \ref{tab:keys} lists valid special key identifiers.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The function returns GLFW\_PRESS if the key is held down, or GLFW\_RELEASE
+if the key is not held down.
+\end{refreturn}
+
+\begin{refdescription}
+The function queries the current state of a specific keyboard key. The
+physical location of each key depends on the system keyboard layout
+setting.
+\end{refdescription}
+
+\begin{refnotes}
+The constant GLFW\_KEY\_SPACE is equal to 32, which is the ISO~8859-1 code
+for space.
+
+Not all key codes are supported on all systems. Also, while some keys are
+available on some keyboard layouts, they may not be available on other
+keyboard layouts.
+
+For systems that do not distinguish between left and right versions of
+modifier keys (shift, alt and control), the left version is used (e.g.
+GLFW\_KEY\_LSHIFT).
+
+A window must be opened for the function to have any effect, and
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers} must be called before any keyboard events are
+recorded and reported by \textbf{glfwGetKey}.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetMouseButton}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+int glfwGetMouseButton( int button )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{button}]\ \\
+ A mouse button identifier, which can be one of the mouse button
+ identifiers listed in table \ref{tab:mousebuttons}.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The function returns GLFW\_PRESS if the mouse button is held down, or
+GLFW\_RELEASE if the mouse button is not held down.
+\end{refreturn}
+
+\begin{refdescription}
+The function queries the current state of a specific mouse button.
+\end{refdescription}
+
+\begin{refnotes}
+A window must be opened for the function to have any effect, and
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers} must be called before any mouse button events
+are recorded and reported by \textbf{glfwGetMouseButton}.
+
+GLFW\_MOUSE\_BUTTON\_LEFT is equal to GLFW\_MOUSE\_BUTTON\_1.
+GLFW\_MOUSE\_BUTTON\_RIGHT is equal to GLFW\_MOUSE\_BUTTON\_2.
+GLFW\_MOUSE\_BUTTON\_MIDDLE is equal to GLFW\_MOUSE\_BUTTON\_3.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetMousePos}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwGetMousePos( int *xpos, int *ypos )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{xpos}]\ \\
+ Pointer to an integer that will be filled out with the horizontal
+ position of the mouse.
+\item [\textit{ypos}]\ \\
+ Pointer to an integer that will be filled out with the vertical
+ position of the mouse.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The function returns the current mouse position in \textit{xpos} and
+\textit{ypos}.
+\end{refreturn}
+
+\begin{refdescription}
+The function returns the current mouse position. If the cursor is not
+hidden, the mouse position is the cursor position, relative to the upper
+left corner of the window and limited to the client area of the window.
+If the cursor is hidden, the mouse position is a virtual absolute
+position, not limited to any boundaries except to those implied by the
+maximum number that can be represented by a signed integer (normally
+-2147483648 to +2147483647).
+\end{refdescription}
+
+\begin{refnotes}
+A window must be opened for the function to have any effect, and
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers} must be called before any mouse movements are
+recorded and reported by \textbf{glfwGetMousePos}.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetMousePos}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetMousePos( int xpos, int ypos )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{xpos}]\ \\
+ Horizontal position of the mouse.
+\item [\textit{ypos}]\ \\
+ Vertical position of the mouse.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function changes the position of the mouse. If the cursor is
+visible (not disabled), the cursor will be moved to the specified
+position, relative to the upper left corner of the window client area.
+If the cursor is hidden (disabled), only the mouse position that is
+reported by \GLFW\ is changed.
+\end{refdescription}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetMouseWheel}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+int glfwGetMouseWheel( void )
+\end{lstlisting}
+
+\begin{refparameters}
+none
+\end{refparameters}
+
+\begin{refreturn}
+The function returns the current mouse wheel position.
+\end{refreturn}
+
+\begin{refdescription}
+The function returns the current mouse wheel position. The mouse wheel can
+be thought of as a third mouse axis, which is available as a separate
+wheel or up/down stick on some mice.
+\end{refdescription}
+
+\begin{refnotes}
+A window must be opened for the function to have any effect, and
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers} must be called before any mouse wheel movements
+are recorded and reported by \textbf{glfwGetMouseWheel}.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetMouseWheel}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetMouseWheel( int pos )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{pos}]\ \\
+ Position of the mouse wheel.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function changes the position of the mouse wheel.
+\end{refdescription}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetKeyCallback}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetKeyCallback( GLFWkeyfun cbfun )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{cbfun}]\ \\
+ Pointer to a callback function that will be called every time a key is
+ pressed or released. The function should have the following C language
+ prototype:
+
+ \texttt{void GLFWCALL functionname( int key, int action );}
+
+ Where \textit{functionname} is the name of the callback function,
+ \textit{key} is a key identifier, which is an uppercase printable
+ ISO~8859-1 character or a special key identifier (see table
+ \ref{tab:keys}), and \textit{action} is either GLFW\_PRESS or
+ GLFW\_RELEASE.
+
+ If \textit{cbfun} is NULL, any previously selected callback function
+ will be deselected.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function selects which function to be called upon a keyboard key
+event. The callback function is called every time the state of a single
+key is changed (from released to pressed or vice versa). The reported keys
+are unaffected by any modifiers (such as shift or alt).
+
+A window has to be opened for this function to have any effect.
+\end{refdescription}
+
+\begin{refnotes}
+Keyboard events are recorded continuously, but only reported when
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers} is called.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetCharCallback}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetCharCallback( GLFWcharfun cbfun )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{cbfun}]\ \\
+ Pointer to a callback function that will be called every time a
+ printable character is generated by the keyboard. The function should
+ have the following C language prototype:
+
+ \texttt{void GLFWCALL functionname( int character, int action );}
+
+ Where \textit{functionname} is the name of the callback function,
+ \textit{character} is a Unicode (ISO~10646) character, and
+ \textit{action} is either GLFW\_PRESS or GLFW\_RELEASE.
+
+ If \textit{cbfun} is NULL, any previously selected callback function
+ will be deselected.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function selects which function to be called upon a keyboard character
+event. The callback function is called every time a key that results in a
+printable Unicode character is pressed or released. Characters are
+affected by modifiers (such as shift or alt).
+
+A window has to be opened for this function to have any effect.
+\end{refdescription}
+
+\begin{refnotes}
+Character events are recorded continuously, but only reported when
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers} is called.
+
+Control characters, such as tab and carriage return, are not reported to
+the character callback function, since they are not part of the Unicode
+character set. Use the key callback function for such events (see
+\textbf{glfwSetKeyCallback}).
+
+The Unicode character set supports character codes above 255, so never
+cast a Unicode character to an eight bit data type (e.g. the C language
+'char' type) without first checking that the character code is less than
+256. Also note that Unicode character codes 0 to 255 are equal to
+ISO~8859-1 (Latin~1).
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetMouseButtonCallback}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetMouseButtonCallback( GLFWmousebuttonfun cbfun )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{cbfun}]\ \\
+ Pointer to a callback function that will be called every time a mouse
+ button is pressed or released. The function should have the following C
+ language prototype:
+
+ \texttt{void GLFWCALL functionname( int button, int action );}
+
+ Where \textit{functionname} is the name of the callback function,
+ \textit{button} is a mouse button identifier (see table
+ \ref{tab:mousebuttons} on page \pageref{tab:mousebuttons}), and
+ \textit{action} is either GLFW\_PRESS or GLFW\_RELEASE.
+
+ If \textit{cbfun} is NULL, any previously selected callback function
+ will be deselected.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function selects which function to be called upon a mouse button
+event.
+
+A window has to be opened for this function to have any effect.
+\end{refdescription}
+
+\begin{refnotes}
+Mouse button events are recorded continuously, but only reported when
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers} is called.
+
+GLFW\_MOUSE\_BUTTON\_LEFT is equal to GLFW\_MOUSE\_BUTTON\_1.
+GLFW\_MOUSE\_BUTTON\_RIGHT is equal to GLFW\_MOUSE\_BUTTON\_2.
+GLFW\_MOUSE\_BUTTON\_MIDDLE is equal to GLFW\_MOUSE\_BUTTON\_3.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetMousePosCallback}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetMousePosCallback( GLFWmouseposfun cbfun )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{cbfun}]\ \\
+ Pointer to a callback function that will be called every time the mouse
+ is moved. The function should have the following C language prototype:
+
+ \texttt{void GLFWCALL functionname( int x, int y );}
+
+ Where \textit{functionname} is the name of the callback function, and
+ \textit{x} and \textit{y} are the mouse coordinates (see
+ \textbf{glfwGetMousePos} for more information on mouse coordinates).
+
+ If \textit{cbfun} is NULL, any previously selected callback function
+ will be deselected.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function selects which function to be called upon a mouse motion event.
+
+A window has to be opened for this function to have any effect.
+\end{refdescription}
+
+\begin{refnotes}
+Mouse motion events are recorded continuously, but only reported when
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers} is called.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetMouseWheelCallback}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetMouseWheelCallback( GLFWmousewheelfun cbfun )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{cbfun}]\ \\
+ Pointer to a callback function that will be called every time the mouse
+ wheel is moved. The function should have the following C language
+ prototype:
+
+ \texttt{void GLFWCALL functionname( int pos );}
+
+ Where \textit{functionname} is the name of the callback function, and
+ \textit{pos} is the mouse wheel position.
+
+ If \textit{cbfun} is NULL, any previously selected callback function
+ will be deselected.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function selects which function to be called upon a mouse wheel event.
+
+A window has to be opened for this function to have any effect.
+\end{refdescription}
+
+\begin{refnotes}
+Mouse wheel events are recorded continuously, but only reported when
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers} is called.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\begin{table}[p]
+\begin{center}
+\begin{tabular}{|l|l|}\hline \raggedright
+\textbf{Name} & \textbf{Return value}\\ \hline
+GLFW\_PRESENT & GL\_TRUE if the joystick is connected, else GL\_FALSE.\\ \hline
+GLFW\_AXES & Number of axes supported by the joystick.\\ \hline
+GLFW\_BUTTONS & Number of buttons supported by the joystick.\\ \hline
+\end{tabular}
+\end{center}
+\caption{Joystick parameters for \textbf{glfwGetJoystickParam}}
+\label{tab:joyparams}
+\end{table}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetJoystickParam}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+int glfwGetJoystickParam( int joy, int param )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{joy}]\ \\
+ A joystick identifier, which should be GLFW\_JOYSTICK\_\textit{n}, where
+ \textit{n} is in the range 1 to 16.
+\item [\textit{param}]\ \\
+ A token selecting which parameter the function should return (see table
+ \ref{tab:joyparams}).
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The function returns different parameters depending on the value of
+\textit{param}. Table \ref{tab:joyparams} lists valid \textit{param}
+values, and their corresponding return values.
+\end{refreturn}
+
+\begin{refdescription}
+The function is used for acquiring various properties of a joystick.
+\end{refdescription}
+
+\begin{refnotes}
+The joystick information is updated every time the function is called.
+
+No window has to be opened for joystick information to be valid.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetJoystickPos}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+int glfwGetJoystickPos( int joy, float *pos, int numaxes )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{joy}]\ \\
+ A joystick identifier, which should be GLFW\_JOYSTICK\_\textit{n}, where
+ \textit{n} is in the range 1 to 16.
+\item [\textit{pos}]\ \\
+ An array that will hold the positional values for all requested axes.
+\item [\textit{numaxes}]\ \\
+ Specifies how many axes should be returned.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The function returns the number of actually returned axes. This is the
+minimum of \textit{numaxes} and the number of axes supported by the
+joystick. If the joystick is not supported or connected, the function will
+return 0 (zero).
+\end{refreturn}
+
+\begin{refdescription}
+The function queries the current position of one or more axes of a
+joystick. The positional values are returned in an array, where the first
+element represents the first axis of the joystick (normally the X axis).
+Each position is in the range -1.0 to 1.0. Where applicable, the positive
+direction of an axis is right, forward or up, and the negative direction
+is left, back or down.
+
+If \textit{numaxes} exceeds the number of axes supported by the joystick,
+or if the joystick is not available, the unused elements in the
+\textit{pos} array will be set to 0.0 (zero).
+\end{refdescription}
+
+\begin{refnotes}
+The joystick state is updated every time the function is called, so there
+is no need to call \textbf{glfwPollEvents} or \textbf{glfwWaitEvents} for
+joystick state to be updated.
+
+Use \textbf{glfwGetJoystickParam} to retrieve joystick capabilities, such
+as joystick availability and number of supported axes.
+
+No window has to be opened for joystick input to be valid.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetJoystickButtons}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+int glfwGetJoystickButtons( int joy, unsigned char *buttons,
+ int numbuttons )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{joy}]\ \\
+ A joystick identifier, which should be GLFW\_JOYSTICK\_\textit{n}, where
+ \textit{n} is in the range 1 to 16.
+\item [\textit{buttons}]\ \\
+ An array that will hold the button states for all requested buttons.
+\item [\textit{numbuttons}]\ \\
+ Specifies how many buttons should be returned.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The function returns the number of actually returned buttons. This is the
+minimum of \textit{numbuttons} and the number of buttons supported by the
+joystick. If the joystick is not supported or connected, the function will
+return 0 (zero).
+\end{refreturn}
+
+\begin{refdescription}
+The function queries the current state of one or more buttons of a
+joystick. The button states are returned in an array, where the first
+element represents the first button of the joystick. Each state can be
+either GLFW\_PRESS or GLFW\_RELEASE.
+
+If \textit{numbuttons} exceeds the number of buttons supported by the
+joystick, or if the joystick is not available, the unused elements in the
+\textit{buttons} array will be set to GLFW\_RELEASE.
+\end{refdescription}
+
+\begin{refnotes}
+The joystick state is updated every time the function is called, so there
+is no need to call \textbf{glfwPollEvents} or \textbf{glfwWaitEvents} for
+joystick state to be updated.
+
+Use \textbf{glfwGetJoystickParam} to retrieve joystick capabilities, such
+as joystick availability and number of supported buttons.
+
+No window has to be opened for joystick input to be valid.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\pagebreak
+\section{Timing}
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetTime}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+double glfwGetTime( void )
+\end{lstlisting}
+
+\begin{refparameters}
+none
+\end{refparameters}
+
+\begin{refreturn}
+The function returns the value of the high precision timer. The time is
+measured in seconds, and is returned as a double precision floating point
+value.
+\end{refreturn}
+
+\begin{refdescription}
+The function returns the state of a high precision timer. Unless the timer
+has been set by the \textbf{glfwSetTime} function, the time is measured as
+the number of seconds that have passed since \textbf{glfwInit} was called.
+\end{refdescription}
+
+\begin{refnotes}
+The resolution of the timer depends on which system the program is running
+on. The worst case resolution is somewhere in the order of $10~ms$, while
+for most systems the resolution should be better than $1~\mu s$.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwSetTime}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwSetTime( double time )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{time}]\ \\
+ Time (in seconds) that the timer should be set to.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+The function sets the current time of the high precision timer to the
+specified time. Subsequent calls to \textbf{glfwGetTime} will be relative
+to this time. The time is given in seconds.
+\end{refdescription}
+
+
+%-------------------------------------------------------------------------
+\pagebreak
+\section{OpenGL Extension Support}
+One of the great features of \OpenGL\ is its support for extensions, which
+allow independent vendors to supply non-standard functionality in their
+\OpenGL\ implementations. Using extensions is different under different
+systems, which is why \GLFW\ has provided an operating system independent
+interface to querying and using \OpenGL\ extensions.
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwExtensionSupported}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+int glfwExtensionSupported( const char *extension )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{extension}]\ \\
+ A null terminated ISO~8859-1 string containing the name of an \OpenGL\
+ extension.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The function returns GL\_TRUE if the extension is supported. Otherwise it
+returns GL\_FALSE.
+\end{refreturn}
+
+\begin{refdescription}
+The function does a string search in the list of supported \OpenGL\
+extensions to find if the specified extension is listed.
+\end{refdescription}
+
+\begin{refnotes}
+An \OpenGL\ context must be created before this function can be called
+(i.e. an \OpenGL\ window must have been opened with
+\textbf{glfwOpenWindow}).
+
+In addition to checking for \OpenGL\ extensions, \GLFW\ also checks for
+extensions in the operating system ``glue API'', such as WGL extensions
+under Windows and glX extensions under the X Window System.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetProcAddress}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void * glfwGetProcAddress( const char *procname )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{procname}]\ \\
+ A null terminated ISO~8859-1 string containing the name of an \OpenGL\
+ extension function.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The function returns the pointer to the specified \OpenGL\ function if it
+is supported, otherwise NULL is returned.
+\end{refreturn}
+
+\begin{refdescription}
+The function acquires the pointer to an \OpenGL\ extension function. Some
+(but not all) \OpenGL\ extensions define new API functions, which are
+usually not available through normal linking. It is therefore necessary to
+get access to those API functions at runtime.
+\end{refdescription}
+
+\begin{refnotes}
+An \OpenGL\ context must be created before this function can be called
+(i.e. an \OpenGL\ window must have been opened with
+\textbf{glfwOpenWindow}).
+
+Some systems do not support dynamic function pointer retrieval, in which
+case \textbf{glfwGetProcAddress} will always return NULL.
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwGetGLVersion}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwGetGLVersion( int *major, int *minor, int *rev )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{major}]\ \\
+ Pointer to an integer that will hold the major version number.
+\item [\textit{minor}]\ \\
+ Pointer to an integer that will hold the minor version number.
+\item [\textit{rev}]\ \\
+ Pointer to an integer that will hold the revision.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+The function returns the major and minor version numbers and the revision
+for the currently used \OpenGL\ implementation.
+\end{refreturn}
+
+\begin{refdescription}
+The function returns the \OpenGL\ implementation version. This is a
+convenient function that parses the version number information from the
+string returned by calling \texttt{glGetString(~GL\_VERSION~)}. The
+\OpenGL\ version information can be used to determine what functionality
+is supported by the used \OpenGL\ implementation.
+\end{refdescription}
+
+\begin{refnotes}
+An \OpenGL\ context must be created before this function can be called
+(i.e. an \OpenGL\ window must have been opened with
+\textbf{glfwOpenWindow}).
+\end{refnotes}
+
+
+%-------------------------------------------------------------------------
+\pagebreak
+\section{Miscellaneous}
+
+
+%-------------------------------------------------------------------------
+\subsection{glfwEnable/glfwDisable}
+
+\textbf{C language syntax}
+\begin{lstlisting}
+void glfwEnable( int token )
+void glfwDisable( int token )
+\end{lstlisting}
+
+\begin{refparameters}
+\begin{description}
+\item [\textit{token}]\ \\
+ A value specifying a feature to enable or disable. Valid tokens are
+ listed in table \ref{tab:enable}.
+\end{description}
+\end{refparameters}
+
+\begin{refreturn}
+none
+\end{refreturn}
+
+\begin{refdescription}
+\textbf{glfwEnable} is used to enable a certain feature, while
+\textbf{glfwDisable} is used to disable it. Below follows a description of
+each feature.
+\end{refdescription}
+
+
+\begin{table}[p]
+\begin{center}
+\begin{tabular}{|l|p{5.0cm}|p{3.0cm}|} \hline \raggedright
+\textbf{Name} & \textbf{Controls} & \textbf{Default}\\ \hline
+\hyperlink{lnk:autopollevents}{GLFW\_AUTO\_POLL\_EVENTS} & Automatic event polling when \textbf{glfwSwapBuffers} is called & Enabled\\ \hline
+\hyperlink{lnk:keyrepeat}{GLFW\_KEY\_REPEAT} & Keyboard key repeat & Disabled\\ \hline
+\hyperlink{lnk:mousecursor}{GLFW\_MOUSE\_CURSOR} & Mouse cursor visibility & Enabled in windowed mode. Disabled in fullscreen mode.\\ \hline
+\hyperlink{lnk:stickykeys}{GLFW\_STICKY\_KEYS} & Keyboard key ``stickiness'' & Disabled\\ \hline
+\hyperlink{lnk:stickymousebuttons}{GLFW\_STICKY\_MOUSE\_BUTTONS} & Mouse button ``stickiness'' & Disabled\\ \hline
+\hyperlink{lnk:systemkeys}{GLFW\_SYSTEM\_KEYS} & Special system key actions & Enabled\\ \hline
+\end{tabular}
+\end{center}
+\caption{Tokens for \textbf{glfwEnable}/\textbf{glfwDisable}}
+\label{tab:enable}
+\end{table}
+
+
+\bigskip\begin{mysamepage}\hypertarget{lnk:autopollevents}{}
+\textbf{GLFW\_AUTO\_POLL\_EVENTS}\\
+When GLFW\_AUTO\_POLL\_EVENTS is enabled, \textbf{glfwPollEvents} is
+automatically called each time that \textbf{glfwSwapBuffers} is called.
+
+When GLFW\_AUTO\_POLL\_EVENTS is disabled, calling
+\textbf{glfwSwapBuffers} will not result in a call to
+\textbf{glfwPollEvents}. This can be useful if \textbf{glfwSwapBuffers}
+needs to be called from within a callback function, since calling
+\textbf{glfwPollEvents} from a callback function is not allowed.
+\end{mysamepage}
+
+
+\bigskip\begin{mysamepage}\hypertarget{lnk:keyrepeat}{}
+\textbf{GLFW\_KEY\_REPEAT}\\
+When GLFW\_KEY\_REPEAT is enabled, the key and character callback
+functions are called repeatedly when a key is held down long enough
+(according to the system key repeat configuration).
+
+When GLFW\_KEY\_REPEAT is disabled, the key and character callback
+functions are only called once when a key is pressed (and once when it is
+released).
+\end{mysamepage}
+
+
+\bigskip\begin{mysamepage}\hypertarget{lnk:mousecursor}{}
+\textbf{GLFW\_MOUSE\_CURSOR}\\
+When GLFW\_MOUSE\_CURSOR is enabled, the mouse cursor is visible, and
+mouse coordinates are relative to the upper left corner of the client area
+of the \GLFW\ window. The coordinates are limited to the client area of
+the window.
+
+When GLFW\_MOUSE\_CURSOR is disabled, the mouse cursor is invisible, and
+mouse coordinates are not limited to the drawing area of the window. It is
+as if the mouse coordinates are recieved directly from the mouse, without
+being restricted or manipulated by the windowing system.
+\end{mysamepage}
+
+
+\bigskip\begin{mysamepage}\hypertarget{lnk:stickykeys}{}
+\textbf{GLFW\_STICKY\_KEYS}\\
+When GLFW\_STICKY\_KEYS is enabled, keys which are pressed will not be
+released until they are physically released and checked with
+\textbf{glfwGetKey}. This behavior makes it possible to catch keys that
+were pressed and then released again between two calls to
+\textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers}, which would otherwise have been reported as
+released. Care should be taken when using this mode, since keys that are
+not checked with \textbf{glfwGetKey} will never be released. Note also
+that enabling GLFW\_STICKY\_KEYS does not affect the behavior of the
+keyboard callback functionality.
+
+When GLFW\_STICKY\_KEYS is disabled, the status of a key that is reported
+by \textbf{glfwGetKey} is always the physical state of the key. Disabling
+GLFW\_STICKY\_KEYS also clears the sticky information for all keys.
+\end{mysamepage}
+
+
+\bigskip\begin{mysamepage}\hypertarget{lnk:stickymousebuttons}{}
+\textbf{GLFW\_STICKY\_MOUSE\_BUTTONS}\\
+When GLFW\_STICKY\_MOUSE\_BUTTONS is enabled, mouse buttons that are
+pressed will not be released until they are physically released and
+checked with \textbf{glfwGetMouseButton}. This behavior makes it
+possible to catch mouse buttons which were pressed and then released again
+between two calls to \textbf{glfwPollEvents}, \textbf{glfwWaitEvents} or
+\textbf{glfwSwapBuffers}, which would otherwise have been reported as
+released. Care should be taken when using this mode, since mouse buttons
+that are not checked with \textbf{glfwGetMouseButton} will never be
+released. Note also that enabling GLFW\_STICKY\_MOUSE\_BUTTONS does not
+affect the behavior of the mouse button callback functionality.
+
+When GLFW\_STICKY\_MOUSE\_BUTTONS is disabled, the status of a mouse
+button that is reported by \textbf{glfwGetMouseButton} is always the
+physical state of the mouse button. Disabling GLFW\_STICKY\_MOUSE\_BUTTONS
+also clears the sticky information for all mouse buttons.
+\end{mysamepage}
+
+
+\bigskip\begin{mysamepage}\hypertarget{lnk:systemkeys}{}
+\textbf{GLFW\_SYSTEM\_KEYS}\\
+When GLFW\_SYSTEM\_KEYS is enabled, pressing standard system key
+combinations, such as \texttt{ALT+TAB} under Windows, will give the normal
+behavior. Note that when \texttt{ALT+TAB} is issued under Windows in this
+mode so that the \GLFW\ application is deselected when \GLFW\ is operating
+in fullscreen mode, the \GLFW\ application window will be minimized and
+the video mode will be set to the original desktop mode. When the \GLFW\
+application is re-selected, the video mode will be set to the \GLFW\ video
+mode again.
+
+When GLFW\_SYSTEM\_KEYS is disabled, pressing standard system key
+combinations will have no effect, since those key combinations are blocked
+by \GLFW . This mode can be useful in situations when the \GLFW\ program
+must not be interrupted (normally for games in fullscreen mode).
+\end{mysamepage}
+
+
+\end{document}
diff --git a/docs/glfwug.tex b/docs/glfwug.tex
new file mode 100644
index 00000000..32a0359b
--- /dev/null
+++ b/docs/glfwug.tex
@@ -0,0 +1,1287 @@
+%-------------------------------------------------------------------------
+% GLFW Users Guide
+% API Version: 2.7
+%-------------------------------------------------------------------------
+
+% Document class
+\documentclass[a4paper,11pt,oneside]{report}
+
+% Document title and API version
+\newcommand{\glfwdoctype}[1][0]{Users Guide}
+\newcommand{\glfwapiver}[1][0]{2.7}
+
+% Common document settings and macros
+\input{glfwdoc.sty}
+
+% PDF specific document settings
+\hypersetup{pdftitle={GLFW Users Guide}}
+\hypersetup{pdfauthor={Marcus Geelnard}}
+\hypersetup{pdfkeywords={GLFW,OpenGL,guide,manual}}
+
+
+%-------------------------------------------------------------------------
+% Document body
+%-------------------------------------------------------------------------
+
+\begin{document}
+
+\pagestyle{plain}
+
+% Title page
+\glfwmaketitle
+
+% Summary, trademarks and table of contents
+\pagenumbering{roman}
+\setcounter{page}{1}
+
+%-------------------------------------------------------------------------
+% Summary and Trademarks
+%-------------------------------------------------------------------------
+\chapter*{Summary}
+
+This document is a users guide for the \GLFW\ API that gives a practical
+introduction to using \GLFW . For a more detailed description of the
+\GLFW\ API you should refer to the \textit{GLFW Reference Manual}.
+\vspace{10cm}
+
+\large
+Trademarks
+
+\small
+OpenGL and IRIX are registered trademarks of Silicon Graphics, Inc.\linebreak
+Microsoft and Windows are registered trademarks of Microsoft Corporation.\linebreak
+Mac OS is a registered trademark of Apple Computer, Inc.\linebreak
+Linux is a registered trademark of Linus Torvalds.\linebreak
+FreeBSD is a registered trademark of Wind River Systems, Inc.\linebreak
+Solaris is a trademark of Sun Microsystems, Inc.\linebreak
+UNIX is a registered trademark of The Open Group.\linebreak
+X Window System is a trademark of The Open Group.\linebreak
+POSIX is a trademark of IEEE.\linebreak
+Truevision, TARGA and TGA are registered trademarks of Truevision, Inc.\linebreak
+IBM is a registered trademark of IBM Corporation.\linebreak
+
+All other trademarks mentioned in this document are the property of their respective owners.
+\normalsize
+
+
+%-------------------------------------------------------------------------
+% Table of contents
+%-------------------------------------------------------------------------
+\tableofcontents
+\pagebreak
+
+
+% Document chapters starts here...
+\pagenumbering{arabic}
+\setcounter{page}{1}
+
+\pagestyle{fancy}
+
+
+%-------------------------------------------------------------------------
+% Introduction
+%-------------------------------------------------------------------------
+\chapter{Introduction}
+\thispagestyle{fancy}
+\GLFW\ is a portable API (Application Program Interface) that handles
+operating system specific tasks related to \OpenGL\ programming. While
+\OpenGL\ in general is portable, easy to use and often results in tidy and
+compact code, the operating system specific mechanisms that are required
+to set up and manage an \OpenGL\ window are quite the opposite. \GLFW\ tries
+to remedy this by providing the following functionality:
+
+\begin{itemize}
+\item Opening and managing an \OpenGL\ window.
+\item Keyboard, mouse and joystick input.
+\item A high precision timer.
+\item Support for querying and using \OpenGL\ extensions.
+\end{itemize}
+\vspace{18pt}
+
+All this functionality is implemented as a set of easy-to-use functions,
+which makes it possible to write an \OpenGL\ application framework in just a
+few lines of code. The \GLFW\ API is completely operating system and
+platform independent, which makes it very simple to port \GLFW\ based \OpenGL\
+applications to a variety of platforms.
+
+Currently supported platforms are:
+\begin{itemize}
+\item Microsoft Windows\textsuperscript{\textregistered} 95/98/ME/NT/2000/XP/.NET Server.
+\item Unix\textsuperscript{\textregistered} or Unix-like systems running the
+X Window System\texttrademark, e.g. Linux\textsuperscript{\textregistered},
+IRIX\textsuperscript{\textregistered}, FreeBSD\textsuperscript{\textregistered},
+Solaris\texttrademark, QNX\textsuperscript{\textregistered} and
+Mac OS\textsuperscript{\textregistered} X.
+\item Mac OS\textsuperscript{\textregistered} X (Carbon)\footnote{Support for joysticks missing at the time of writing.}
+\end{itemize}
+
+
+%-------------------------------------------------------------------------
+% Getting Started
+%-------------------------------------------------------------------------
+\chapter{Getting Started}
+\thispagestyle{fancy}
+In this chapter you will learn how to write a simple \OpenGL\ application
+using \GLFW . We start by initializing \GLFW , then we open a window and
+read some user keyboard input.
+
+
+%-------------------------------------------------------------------------
+\section{Initializing GLFW}
+Before using any of the \GLFW\ functions, it is necessary to call
+\textbf{glfwInit}. It initializes internal working variables that are used
+by other \GLFW\ functions. The C syntax is:
+
+\begin{lstlisting}
+int glfwInit( void )
+\end{lstlisting}
+
+\textbf{glfwInit} returns GL\_TRUE if initialization succeeded, or
+GL\_FALSE if it failed.
+
+When your application is done using \GLFW , typically at the very end of
+the program, you should call \textbf{glfwTerminate}, which makes a clean
+up and places \GLFW\ in a non-initialized state (i.e. it is necessary to
+call \textbf{glfwInit} again before using any \GLFW\ functions). The C
+syntax is:
+
+\begin{lstlisting}
+void glfwTerminate( void )
+\end{lstlisting}
+
+Among other things, \textbf{glfwTerminate} closes the \OpenGL\ window
+unless it was closed manually.
+
+
+%-------------------------------------------------------------------------
+\section{Opening An OpenGL Window}
+Opening an \OpenGL\ window is done with the function
+\textbf{glfwOpenWindow}. The function takes nine arguments, which are used
+to describe the following properties of the window to open:
+
+\begin{itemize}
+\item Window dimensions (width and height) in pixels.
+\item Color and alpha buffer depth.
+\item Depth buffer (Z-buffer) depth.
+\item Stencil buffer depth.
+\item Fullscreen or windowed mode.
+\end{itemize}
+
+The C language syntax for \textbf{glfwOpenWindow} is:
+\begin{lstlisting}
+int glfwOpenWindow( int width, int height,
+ int redbits, int greenbits, int bluebits,
+ int alphabits, int depthbits, int stencilbits,
+ int mode )
+\end{lstlisting}
+
+\textbf{glfwOpenWindow} returns GL\_TRUE if the window was opened
+correctly, or GL\_FALSE if \GLFW\ failed to open the window.
+
+\GLFW\ tries to open a window that best matches the requested parameters.
+Some parameters may be omitted by setting them to zero, which will result
+in \GLFW\ either using a default value, or the related functionality to be
+disabled. For instance, if \textit{width} and \textit{height} are both
+zero, \GLFW\ will use a window resolution of 640x480. If
+\textit{depthbits} is zero, the opened window may not have a depth buffer.
+
+The \textit{mode} argument is used to specify if the window is to be a
+s.c. fullscreen window, or a regular window.
+
+If \textit{mode} is GLFW\_FULLSCREEN, the window will cover the entire
+screen and no window borders will be visible. If possible, the video mode
+will be changed to the mode that closest matches the \textit{width},
+\textit{height}, \textit{redbits}, \textit{greenbits}, \textit{bluebits}
+and \textit{alphabits} arguments. Furthermore, the mouse pointer will be
+hidden, and screensavers are prohibited. This is usually the best mode for
+games and demos.
+
+If \textit{mode} is GLFW\_WINDOW, the window will be opened as a normal
+window on the desktop. The mouse pointer will not be hidden, and
+screensavers are allowed to be activated.
+
+To close the window, you can either use \textbf{glfwTerminate}, as
+described earlier, or you can use the more explicit approach by calling
+\textbf{glfwCloseWindow}, which has the C syntax:
+
+\begin{lstlisting}
+void glfwCloseWindow( void )
+\end{lstlisting}
+
+
+%-------------------------------------------------------------------------
+\section{Using Keyboard Input}
+\GLFW\ provides several means for receiving user input, which will be
+discussed in more detail in chapter \ref{par:inputhandling}. One of the
+simplest ways of checking for keyboard input is to use the function
+\textbf{glfwGetKey}:
+
+\begin{lstlisting}
+int glfwGetKey( int key )
+\end{lstlisting}
+
+It queries the current status of individual keyboard keys. The argument
+\textit{key} specifies which key to check, and it can be either an
+uppercase printable ISO 8859-1 (Latin 1) character (e.g. `A', `3' or `.'),
+or a special key identifier (see the \textit{GLFW Reference Manual} for a
+list of special key identifiers). \textbf{glfwGetKey} returns GLFW\_PRESS
+(or 1) if the key is currently held down, or GLFW\_RELEASE (or 0) if the
+key is not being held down. For example:
+
+\begin{lstlisting}
+A_pressed = glfwGetKey( 'A' );
+esc_pressed = glfwGetKey( GLFW_KEY_ESC );
+\end{lstlisting}
+
+In order for \textbf{glfwGetKey} to have any effect, you need to poll for
+input events on a regular basis. This can be done in one of two ways:
+
+\begin{enumerate}
+\item Implicitly by calling \textbf{glfwSwapBuffers} often.
+\item Explicitly by calling \textbf{glfwPollEvents} often.
+\end{enumerate}
+
+In general you do not have to care about this, since you will normally
+call \textbf{glfwSwapBuffers} to swap front and back rendering buffers
+every animation frame anyway. If, however, this is not the case, you
+should call \textbf{glfwPollEvents} in the order of 10-100 times per
+second in order for \GLFW\ to maintain an up to date input state.
+
+
+%-------------------------------------------------------------------------
+\section{Putting It Together: A Minimal GLFW Application}
+Now that you know how to initialize \GLFW , open a window and poll for
+keyboard input, let us exemplify this with a simple \OpenGL\ program. In
+the following example some error-checking has been omitted for the sake of
+brevity:
+
+\begin{lstlisting}
+#include
+
+int main( void )
+{
+ int running = GL_TRUE;
+
+ // Initialize GLFW
+ glfwInit();
+
+ // Open an OpenGL window
+ if( !glfwOpenWindow( 300,300, 0,0,0,0,0,0, GLFW_WINDOW ) )
+ {
+ glfwTerminate();
+ return 0;
+ }
+
+ // Main loop
+ while( running )
+ {
+ // OpenGL rendering goes here...
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Swap front and back rendering buffers
+ glfwSwapBuffers();
+
+ // Check if ESC key was pressed or window was closed
+ running = !glfwGetKey( GLFW_KEY_ESC ) &&
+ glfwGetWindowParam( GLFW_OPENED );
+ }
+
+ // Close window and terminate GLFW
+ glfwTerminate();
+
+ // Exit program
+ return 0;
+}
+\end{lstlisting}
+
+The program opens a 300x300 window and runs in a loop until the escape key
+is pressed, or the window was closed. All the \OpenGL\ ``rendering'' that
+is done in this example is to clear the window.
+
+
+%-------------------------------------------------------------------------
+% Window Operations
+%-------------------------------------------------------------------------
+\chapter{Window Operations}
+\thispagestyle{fancy}
+In this chapter, you will learn more about window related \GLFW\
+functionality, including: setting and getting window properties, buffer
+swap control and video mode querying.
+
+
+%-------------------------------------------------------------------------
+\section{Setting Window Properties}
+In the previous chapter the \textbf{glfwOpenWindow} function was
+described, which specifies the sizes of the color, alpha, depth and
+stencil buffers. It is also possible to request an accumulator buffer,
+auxiliary buffers and stereo rendering by using the
+\textbf{glfwOpenWindowHint} function:
+
+\begin{lstlisting}
+void glfwOpenWindowHint( int target, int hint )
+\end{lstlisting}
+
+The \textit{target} argument can be one of the constants listed in table~
+\ref{tab:winhints}, and \textit{hint} is the value to assign to the
+specified target.
+
+%-------------------------------------------------------------------------
+\begin{table}[p]
+\begin{center}
+\begin{tabular}{|l|l|p{7.0cm}|} \hline \raggedright
+\textbf{Name} & \textbf{Default} & \textbf{Description} \\ \hline
+GLFW\_REFRESH\_RATE & 0 & Vertical monitor refresh rate in Hz (only used for fullscreen windows). Zero means system default.\\ \hline
+GLFW\_ACCUM\_RED\_BITS & 0 & Number of bits for the red channel of the accumulator buffer.\\ \hline
+GLFW\_ACCUM\_GREEN\_BITS & 0 & Number of bits for the green channel of the accumulator buffer.\\ \hline
+GLFW\_ACCUM\_BLUE\_BITS & 0 & Number of bits for the blue channel of the accumulator buffer.\\ \hline
+GLFW\_ACCUM\_ALPHA\_BITS & 0 & Number of bits for the alpha channel of the accumulator buffer.\\ \hline
+GLFW\_AUX\_BUFFERS & 0 & Number of auxiliary buffers.\\ \hline
+GLFW\_STEREO & GL\_FALSE & Specify if stereo rendering should be supported (can be GL\_TRUE or GL\_FALSE).\\ \hline
+GLFW\_WINDOW\_NO\_RESIZE & GL\_FALSE & Specify whether the window can be resized (not used for fullscreen windows).\\ \hline
+GLFW\_FSAA\_SAMPLES & 0 & Number of samples to use for the multisampling buffer. Zero disables multisampling.\\ \hline
+GLFW\_OPENGL\_VERSION\_MAJOR & 0 & Major number of the desired OpenGL version.
+ The default requests the highest OpenGL version equal to or lower than 2.1.\\ \hline
+GLFW\_OPENGL\_VERSION\_MINOR & 0 & Minor number of the desired OpenGL version.
+ The default requests the highest OpenGL version equal to or lower than 2.1.\\ \hline
+GLFW\_OPENGL\_FORWARD\_COMPAT & GL\_FALSE & Specify whether the OpenGL context should be forward compatible (i.e. disallow legacy functionality).
+ This hint is ignored for OpenGL version 2.1 and below.\\ \hline
+\end{tabular}
+\end{center}
+\caption{Targets for \textbf{glfwOpenWindowHint}}
+\label{tab:winhints}
+\end{table}
+%-------------------------------------------------------------------------
+
+For a hint to have any effect, the \textbf{glfwOpenWindowHint} function
+must be called before opening the window with the \textbf{glfwOpenWindow}
+function.
+
+To request an accumulator buffer, set the GLFW\_ACCUM\_x\_BITS targets to
+values greater than zero (usually eight or sixteen bits per component).
+To request auxiliary buffers, set the GLFW\_AUX\_BUFFERS target to a value
+greater than zero. To request a stereo rendering capable window, set the
+GLFW\_STEREO target to GL\_TRUE.
+
+If you want to enable fullscreen antialiasing, set the GLFW\_FSAA\_SAMPLES
+target to a value greater than zero. If the windowing system is unable to
+fulfil the request, \GLFW\ will degrade gracefully and disable FSAA if necessary.
+
+The GLFW\_REFRESH\_RATE target should be used with caution, since it may
+result in suboptimal operation, or even a blank or damaged screen.
+
+If you want to create a context with OpenGL version 3.0 or above you have to
+set the GLFW\_OPENGL\_VERSION\_MAJOR and GLFW\_OPENGL\_VERSION\_MINOR hints
+accordingly. If you don't do this, the highest OpenGL version available for a
+context is 2.1 or lower.
+
+Besides the parameters that are given with the \textbf{glfwOpenWindow} and
+\textbf{glfwOpenWindowHint} functions, a few more properties of a window
+can be changed after the window has been opened, namely the window title,
+window size, and window position.
+
+To change the window title of an open window, use the
+\textbf{glfwSetWindowTitle} function:
+
+\begin{lstlisting}
+void glfwSetWindowTitle( const char *title )
+\end{lstlisting}
+
+\textit{title} is a null terminated ISO~8859-1 (8-bit Latin~1) string that
+will be used as the window title. It will also be used as the application
+name (for instance in the application list when using \texttt{ALT+TAB}
+under Windows, or as the icon name when the window is iconified under
+the X Window System). The default window name is ``GLFW Window'', which
+will be used unless \textbf{glfwSetWindowTitle} is called after the window
+has been opened.
+
+To change the size of a window, call \textbf{glfwSetWindowSize}:
+
+\begin{lstlisting}
+void glfwSetWindowSize( int width, int height )
+\end{lstlisting}
+
+Where \textit{width} and \textit{height} are the new dimensions of the
+window.
+
+To change the position of a window, call \textbf{glfwSetWindowPos}:
+
+\begin{lstlisting}
+void glfwSetWindowPos( int x, int y )
+\end{lstlisting}
+
+Where \textit{x} and \textit{y} are the new desktop coordinates of the
+window. This function does not have any effect when in fullscreen mode.
+
+
+%-------------------------------------------------------------------------
+\section{Getting Window Properties}
+When opening a window, the opened window will not necessarily have the
+requested properties, so you should always check the parameters that your
+application relies on (e.g. number of stencil bits) using
+\textbf{glfwGetWindowParam}, which has the C syntax:
+
+\begin{lstlisting}
+int glfwGetWindowParam( int param )
+\end{lstlisting}
+
+The argument \textit{param} can be one of the tokens listed in table
+\ref{tab:winparams}, and the return value is an integer holding the
+requested value.
+
+%-------------------------------------------------------------------------
+\begin{table}[p]
+\begin{center}
+\begin{tabular}{|l|p{9.5cm}|} \hline \raggedright
+\textbf{Name} & \textbf{Description} \\ \hline
+GLFW\_OPENED & GL\_TRUE if window is opened, else GL\_FALSE.\\ \hline
+GLFW\_ACTIVE & GL\_TRUE if window has focus, else GL\_FALSE.\\ \hline
+GLFW\_ICONIFIED & GL\_TRUE if window is iconified, else GL\_FALSE.\\ \hline
+GLFW\_ACCELERATED & GL\_TRUE if window is hardware accelerated, else GL\_FALSE.\\ \hline
+GLFW\_RED\_BITS & Number of bits for the red color component.\\ \hline
+GLFW\_GREEN\_BITS & Number of bits for the green color component.\\ \hline
+GLFW\_BLUE\_BITS & Number of bits for the blue color component.\\ \hline
+GLFW\_ALPHA\_BITS & Number of bits for the alpha buffer.\\ \hline
+GLFW\_DEPTH\_BITS & Number of bits for the depth buffer.\\ \hline
+GLFW\_STENCIL\_BITS & Number of bits for the stencil buffer.\\ \hline
+GLFW\_REFRESH\_RATE & Vertical monitor refresh rate in Hz. Zero indicates an unknown or a default refresh rate.\\ \hline
+GLFW\_ACCUM\_RED\_BITS & Number of bits for the red channel of the accumulator buffer.\\ \hline
+GLFW\_ACCUM\_GREEN\_BITS & Number of bits for the green channel of the accumulator buffer.\\ \hline
+GLFW\_ACCUM\_BLUE\_BITS & Number of bits for the blue channel of the accumulator buffer.\\ \hline
+GLFW\_ACCUM\_ALPHA\_BITS & Number of bits for the alpha channel of the accumulator buffer.\\ \hline
+GLFW\_AUX\_BUFFERS & Number of auxiliary buffers.\\ \hline
+GLFW\_STEREO & GL\_TRUE if stereo rendering is supported, else GL\_FALSE.\\ \hline
+GLFW\_WINDOW\_NO\_RESIZE & GL\_TRUE if the window cannot be resized, else GL\_FALSE.\\ \hline
+GLFW\_FSAA\_SAMPLES & Number of multisampling buffer samples. Zero indicated multisampling is disabled.\\ \hline
+GLFW\_OPENGL\_VERSION\_MAJOR & Major number of the desired OpenGL version.\\ \hline
+GLFW\_OPENGL\_VERSION\_MINOR & Minor number of the desired OpenGL version.\\ \hline
+GLFW\_OPENGL\_FORWARD\_COMPAT & GL\_TRUE if the OpenGL context is forward compatible (i.e. disallows legacy functionality), else GL\_FALSE.
+This is always GL\_FALSE for OpenGL version 2.1 and below.\\ \hline
+\end{tabular}
+\end{center}
+\caption{Window parameters for \textbf{glfwGetWindowParam}}
+\label{tab:winparams}
+\end{table}
+%-------------------------------------------------------------------------
+
+Another useful function is \textbf{glfwSetWindowSizeCallback}, which
+specifies a user function that will be called every time the window size
+has changed. The C syntax is:
+
+\begin{lstlisting}
+void glfwSetWindowSizeCallback( GLFWwindowsizefun cbfun )
+\end{lstlisting}
+
+The user function \textit{fun} should be of the type:
+
+\begin{lstlisting}
+void GLFWCALL fun( int width, int height )
+\end{lstlisting}
+
+The first argument passed to the user function is the width of the window,
+and the second argument is the height of the window. Here is an example
+of how to use a window size callback function:
+
+\begin{lstlisting}
+int WinWidth, WinHeight;
+
+void GLFWCALL WindowResize( int width, int height )
+{
+ WinWidth = width;
+ WinHeight = height;
+}
+
+int main( void )
+{
+ ...
+ glfwSetWindowSizeCallback( WindowResize );
+ ...
+}
+\end{lstlisting}
+
+Using a callback function for getting the window size is mostly useful for
+windowed applications, since the window size may be changed at any time by
+the user. It can also be used to determine the actual fullscreen
+resolution.
+
+An alternative to using a callback function for getting the window size,
+is to use the function \textbf{glfwGetWindowSize}:
+
+\begin{lstlisting}
+void glfwGetWindowSize( int *width, int *height )
+\end{lstlisting}
+
+The \textit{width} and \textit{height} arguments are filled out with the
+current window dimensions.
+
+
+%-------------------------------------------------------------------------
+\section{Buffer Swapping}
+\GLFW\ windows are always double buffered. That means that you have two
+rendering buffers; a front buffer and a back buffer. The front buffer is
+the buffer that is being displayed, and the back buffer is not displayed.
+\OpenGL\ lets you select which of these two buffers you want to render to
+(with the \textbf{glDrawBuffer} command), but the default (and preferred)
+rendering buffer is the back buffer. This way you will avoid flickering
+and artifacts caused by graphics being only partly drawn at the same time
+as the video raster beam is displaying the graphics on the monitor.
+
+When an entire frame has been rendered to the back buffer, it is time to
+swap the back and the front buffers in order to display the rendered
+frame, and begin rendering a new frame. This is done with the command
+\textbf{glfwSwapBuffers}. The C syntax is:
+
+\begin{lstlisting}
+void glfwSwapBuffers( void )
+\end{lstlisting}
+
+Besides swapping the front and back rendering buffers,
+\textbf{glfwSwapBuffers} also calls \textbf{glfwPollEvents}\footnote{This
+behavior can be disabled by calling \textbf{glfwDisable} with the argument
+GLFW\_AUTO\_POLL\_EVENTS.}. This is to ensure frequent polling of events,
+such as keyboard and mouse input, and window reshaping events.
+
+Sometimes it can be useful to select when the buffer swap will occur. With
+the function \textbf{glfwSwapInterval} it is possible to select the
+minimum number of vertical retraces the video raster line should do before
+swapping the buffers:
+
+\begin{lstlisting}
+void glfwSwapInterval( int interval )
+\end{lstlisting}
+
+If \textit{interval} is zero, the swap will take place immediately when
+\textbf{glfwSwapBuffers} is called, without waiting for a vertical retrace
+(also known as ``vsync off''). Otherwise at least \textit{interval}
+retraces will pass between each buffer swap (also known as ``vsync on'').
+Using a swap interval of zero can be useful for benchmarking purposes,
+when it is not desirable to measure the time it takes to wait for the
+vertical retrace. However, a swap interval of 1 generally gives better
+visual quality.
+
+It should be noted that not all \OpenGL\ implementations and hardware
+support this function, in which case \textbf{glfwSwapInterval} will have
+no effect. Sometimes it is only possible to affect the swap interval
+through driver settings (e.g. the display settings under Windows, or as an
+environment variable setting under Unix).
+
+
+%-------------------------------------------------------------------------
+\section{Querying Video Modes}
+Although \GLFW\ generally does a good job at selecting a suitable video
+mode for you when you open a fullscreen window, it is sometimes useful to
+know exactly which modes are available on a certain system. For example,
+you may want to present the user with a list of video modes to select
+from. To get a list of available video modes, you can use the function
+\textbf{glfwGetVideoModes}:
+
+\begin{lstlisting}
+int glfwGetVideoModes( GLFWvidmode *list, int maxcount )
+\end{lstlisting}
+
+The argument \textit{list} is a vector of GLFWvidmode structures, and
+\textit{maxcount} is the maximum number of video modes that your vector
+can hold. \textbf{glfwGetVideoModes} will return the actual number of
+video modes detected on the system.
+
+The GLFWvidmode structure looks like this:
+
+\begin{lstlisting}
+typedef struct {
+ int Width, Height; // Video resolution
+ int RedBits; // Red bits per pixel
+ int GreenBits; // Green bits per pixel
+ int BlueBits; // Blue bits per pixel
+} GLFWvidmode;
+\end{lstlisting}
+
+Here is an example of retrieving all available video modes:
+
+\begin{lstlisting}
+int nummodes;
+GLFWvidmode list[ 200 ];
+nummodes = glfwGetVideoModes( list, 200 );
+\end{lstlisting}
+
+The returned list is sorted, first by color depth ($RedBits + GreenBits +
+BlueBits$), and then by resolution ($Width\times Height$), with the
+lowest resolution, fewest bits per pixel mode first.
+
+To get the desktop video mode, use the function
+\textbf{glfwGetDesktopMode}:
+
+\begin{lstlisting}
+void glfwGetDesktopMode( GLFWvidmode *mode )
+\end{lstlisting}
+
+The function returns the resolution and color depth of the user desktop in
+the mode structure. Note that the user desktop mode is independent of the
+current video mode if a \GLFW\ fullscreen window has been opened.
+
+
+%-------------------------------------------------------------------------
+% Input Handling
+%-------------------------------------------------------------------------
+\chapter{Input Handling}
+\label{par:inputhandling}
+\thispagestyle{fancy}
+In this chapter you will learn how to use keyboard, mouse and joystick
+input, using either polling or callback functions.
+
+
+%-------------------------------------------------------------------------
+\section{Event Polling}
+The first thing to know about input handling in \GLFW\ is that all
+keyboard and mouse input is collected by checking for input events. This
+has do be done manually by calling either \textbf{glfwPollEvents} or
+\textbf{glfwSwapBuffers} (which implicitly calls \textbf{glfwPollEvents}
+for you). Normally this does not have to be a concern, since
+\textbf{glfwSwapBuffers} is called every frame, which should be often
+enough (about 10-100 times per second for a normal \OpenGL\ application).
+One exception is when rendering is paused, and then the program waits for
+input to begin animation again. In this case \textbf{glfwPollEvents} has
+to be called repeatedly until any new input events arrive.
+
+If it is not desirable that \textbf{glfwPollEvents is} called implicitly
+from \textbf{glfwSwapBuffers}, call \textbf{glfwDisable} with the argument
+GLFW\_AUTO\_POLL\_EVENTS.
+
+Note that event polling is not needed for joystick input, since all
+relevant joystick state is gathered every time a joystick function is
+called.
+
+
+%-------------------------------------------------------------------------
+\section{Keyboard Input}
+\GLFW\ gives three options for getting keyboard input:
+
+\begin{itemize}
+\item Manually polling the state of individual keys.
+\item Automatically receive new key state for any key, using a callback
+ function.
+\item Automatically receive characters, using a callback function.
+\end{itemize}
+
+Depending on what the keyboard input will be used for, either of the
+methods may be more suitable. The main difference between the two last
+options is that while characters are affected by modifier keys (such as
+shift), key state is independent of any modifier keys. Also, special keys
+(such as function keys, cursor keys and modifier keys) are not reported to
+the character callback function.
+
+%-------------------------------------------------------------------------
+\subsection{Key state}
+To check if a key is held down or not at any given moment, use the
+function \textbf{glfwGetKey}:
+
+\begin{lstlisting}
+int glfwGetKey( int key )
+\end{lstlisting}
+
+It queries the current status of individual keyboard keys. The argument
+\textit{key} specifies which key to check, and it can be either an
+uppercase ISO~8859-1 character, or a special key identifier.
+\textbf{glfwGetKey} returns GLFW\_PRESS (or 1) if the key is currently
+held down, or GLFW\_RELEASE (or 0) if the key is not being held down.
+
+In most situations, it may be useful to know if a key has been pressed and
+released between two calls to \textbf{glfwGetKey} (especially if the
+animation is fairly slow, which may allow the user to press and release a
+key between two calls to \textbf{glfwGetKey}). This can be accomplished by
+enabling sticky keys, which is done by calling \textbf{glfwEnable} with
+the argument GLFW\_STICKY\_KEYS, as in the following example:
+
+\begin{lstlisting}
+glfwEnable( GLFW_STICKY_KEYS );
+\end{lstlisting}
+
+When sticky keys are enabled, a key will not be released until it is
+checked with \textbf{glfwGetKey}. To disable sticky keys, call
+\textbf{glfwDisable} witht the argument GLFW\_STICKY\_KEYS. Then all keys
+that are not currently held down will be released, and future key releases
+will take place immediately when the user releases the key, without
+waiting for \textbf{glfwGetKey} to check the key. By default sticky keys
+are disabled.
+
+Sticky keys are often very useful and should be used in most cases where
+\textbf{glfwGetKey} is used. There is however a danger involved with
+enabling sticky keys, and that is that keys that are pressed by the user
+but are not checked with \textbf{glfwGetKey}, may remain ``pressed'' for a
+very long time. A typical situation where this may be dangerous is in a
+program that consists of two or more sections (e.g. a menu section and a
+game section). If the first section enables sticky keys but does not check
+for keys which the second section checks for, there is a potential of
+recording many key presses in the first section that will be detected in
+the second section. To avoid this problem, always disable sticky keys
+before leaving a section of a program.
+
+An alternative to using \textbf{glfwGetKey} is to register a keyboard
+input callback function with \textbf{glfwSetKeyCallback}:
+
+\begin{lstlisting}
+void glfwSetKeyCallback( GLFWkeyfun cbfun )
+\end{lstlisting}
+
+The argument \textit{fun} is a pointer to a callback function. The
+callback function shall take two integer arguments. The first is the key
+identifier, and the second is the new key state, which can be GLFW\_PRESS
+or GLFW\_RELEASE. To unregister a callback function, call
+\textbf{glfwSetKeyCallback} with \textit{fun} = NULL.
+
+A callback function can be useful in some situations. For instance it can
+replace multiple \textbf{glfwGetKey} calls with a switch/case statement.
+
+%-------------------------------------------------------------------------
+\subsection{Character input}
+If the keyboard is to be used as a text input device (e.g. in a user
+dialog) rather than as a set of independent buttons, a character callback
+function is more suitable. To register a character callback function, use
+\textbf{glfwSetCharCallback}:
+
+\begin{lstlisting}
+void glfwSetCharCallback( GLFWcharfun cbfun )
+\end{lstlisting}
+
+The argument \textit{fun} is a pointer to a callback function. The
+callback function shall take two integer arguments. The first is a Unicode
+character code, and the second is GLFW\_PRESS if the key that generated
+the character was pressed, or GLFW\_RELEASE if it was released. To
+unregister a callback function, call \textbf{glfwSetCharCallback} with
+\textit{fun} = NULL.
+
+The Unicode character set is an international standard for encoding
+characters. It is much more comprehensive than seven or eight bit
+character sets (e.g. US-ASCII and Latin~1), and includes characters for
+most written languages in the world. It should be noted that Unicode
+character codes 0 to 255 are the same as for ISO~8859-1 (Latin~1), so as
+long as a proper range check is performed on the Unicode character code,
+it can be used just as an eight bit Latin~1 character code (which can be
+useful if full Unicode support is not possible).
+
+
+%-------------------------------------------------------------------------
+\subsection{Key repeat}
+By default, \GLFW\ does not report key repeats when a key is held down.
+To activate key repeat, call \textbf{glfwEnable} with the argument
+GLFW\_KEY\_REPEAT:
+
+\begin{lstlisting}
+glfwEnable( GLFW_KEY_REPEAT );
+\end{lstlisting}
+
+This will let a registered key or character callback function receive key
+repeat events when a key is held down.
+
+
+%-------------------------------------------------------------------------
+\subsection{Special system keys}
+On most systems there are some special system keys that are normally not
+intercepted by an application. For instance, under Windows it is possible
+to switch programs by pressing \texttt{ALT+TAB}, which brings up a list of
+running programs to select from. In certain situations it can be desirable
+to prevent such special system keys from interfering with the program.
+With \GLFW\ it is possible to do by calling \textbf{glfwDisable} with the
+argument GLFW\_SYSTEM\_KEYS:
+
+\begin{lstlisting}
+glfwDisable( GLFW_SYSTEM_KEYS );
+\end{lstlisting}
+
+By doing so, most system keys will have no effect and will not interfere
+with your program. System keys can be re-enabled by calling
+\textbf{glfwEnable} with the argument GLFW\_SYSTEM\_KEYS. By default,
+system keys are enabled.
+
+
+%-------------------------------------------------------------------------
+\section{Mouse Input}
+Just like for keyboard input, mouse input can be realized with either
+polling or callback functions.
+
+
+%-------------------------------------------------------------------------
+\subsection{Mouse position}
+To read the mouse position, you can use the function
+\textbf{glfwGetMousePos}:
+
+\begin{lstlisting}
+void glfwGetMousePos( int *x, int *y )
+\end{lstlisting}
+
+The arguments \textit{x} and \textit{y} point to integer variables that
+will be updated with the current absolute mouse position. An alternative
+is to use a callback function instead, which can be set with
+\textbf{glfwSetMousePosCallback}:
+
+\begin{lstlisting}
+void glfwSetMousePosCallback( GLFWmouseposfun cbfun )
+\end{lstlisting}
+
+The function that \textit{fun} points to will be called every time the
+mouse position changes. The first argument to the callback function is
+the mouse x position, and the second argument is the mouse y position.
+
+
+%-------------------------------------------------------------------------
+\subsection{Mouse buttons}
+To query the state of a mouse button, call \textbf{glfwGetMouseButton}:
+
+\begin{lstlisting}
+int glfwGetMouseButton( int button )
+\end{lstlisting}
+
+The argument \textit{button} can be one of the following mouse button
+identifiers: GLFW\_MOUSE\_BUTTON\_LEFT, GLFW\_MOUSE\_BUTTON\_RIGHT or
+GLFW\_MOUSE\_BUTTON\_MIDDLE. \textbf{glfwGetMouseButton} will return
+GLFW\_PRESS (which is a non-zero value) if the corresponding mouse
+button is held down, otherwise it will return GLFW\_RELEASE (which is
+equal to zero).
+
+Just as it is possible to make keys ``sticky'', it is also possible to
+make mouse buttons appear as held down until the button is checked for
+with \textbf{glfwGetMouseButton}. To enable sticky mouse buttons, call
+\textbf{glfwEnable} with the argument GLFW\_STICKY\_MOUSE\_BUTTONS.
+
+When sticky mouse buttons are enabled, a mouse button will not be released
+until it is checked with \textbf{glfwGetMouseButton}. To disable sticky
+mouse buttons, call \textbf{glfwDisable} with the argument
+GLFW\_STICKY\_MOUSE\_BUTTONS. Then all mouse buttons that are not
+currently held down will be released, and future mouse button releases
+will take place immediately when the user releases the mouse button,
+without waiting for \textbf{glfwGetMouseButton} to check for the mouse
+button. By default sticky mouse buttons are disabled.
+
+There is also a callback function for mouse button activities, which can
+be set with \textbf{glfwSetMouseButtonCallback}:
+
+\begin{lstlisting}
+void glfwSetMouseButtonCallback( GLFWmousebuttonfun fun )
+\end{lstlisting}
+
+The argument \textit{fun} specifies a function that will be called
+whenever a mouse button is pressed or released, or NULL to unregister a
+callback function. The first argument to the callback function is a mouse
+button identifier, and the second is either GLFW\_PRESS or GLFW\_RELEASE,
+depending on the new state of the corresponding mouse button.
+
+
+%-------------------------------------------------------------------------
+\subsection{Mouse wheel}
+Some mice have a mouse wheel, which can be thought of as a third mouse
+axis. To get the position of the mouse wheel, call
+\textbf{glfwGetMouseWheel}:
+
+\begin{lstlisting}
+int glfwGetMouseWheel( void )
+\end{lstlisting}
+
+The function returns an integer that represents the position of the mouse
+wheel. When the user turns the wheel, the wheel position will increase or
+decrease.
+
+It is also possible to register a callback function for mouse wheel events
+with the \textbf{glfwSetMouseWheelCallback} function:
+
+\begin{lstlisting}
+void glfwSetMouseWheelCallback( GLFWmousewheelfun fun )
+\end{lstlisting}
+
+The argument \textit{fun} specifies a function that will be called
+whenever the mouse wheel is moved, or NULL to unregister a callback
+function. The argument to the callback function is the position of the
+mouse wheel.
+
+
+%-------------------------------------------------------------------------
+\subsection{Hiding the mouse cursor}
+It is possible to hide the mouse cursor with the function call:
+
+\begin{lstlisting}
+glfwDisable( GLFW_MOUSE_CURSOR );
+\end{lstlisting}
+
+Hiding the mouse cursor has three effects:
+
+\begin{enumerate}
+\item The cursor becomes invisible.
+\item The cursor is guaranteed to be confined to the window.
+\item Mouse coordinates are not limited to the window size.
+\end{enumerate}
+
+To show the mouse cursor again, call \textbf{glfwEnable} with the
+argument GLFW\_MOUSE\_CURSOR:
+
+\begin{lstlisting}
+glfwEnable( GLFW_MOUSE_CURSOR );
+\end{lstlisting}
+
+By default the mouse cursor is hidden if a window is opened in fullscreen
+mode, otherwise it is not hidden.
+
+
+%-------------------------------------------------------------------------
+\section{Joystick Input}
+\GLFW\ has support for up to sixteen joysticks, and an infinite\footnote{%
+There are of course actual limitations posed by the underlying hardware,
+drivers and operation system.} number of axes and buttons per joystick.
+Unlike keyboard and mouse input, joystick input does not need an opened
+window, and \textbf{glfwPollEvents} or \textbf{glfwSwapBuffers} does not
+have to be called in order for joystick state to be updated.
+
+
+%-------------------------------------------------------------------------
+\subsection{Joystick capabilities}
+First, it is often necessary to determine if a joystick is connected, and
+what its capabilities are. To get this information the function
+\textbf{glfwGetJoystickParam} can be used:
+
+\begin{lstlisting}
+int glfwGetJoystickParam( int joy, int param )
+\end{lstlisting}
+
+The \textit{joy} argument specifies which joystick to retrieve the
+parameter from, and it should be GLFW\_JOYSTICK\_\textit{n}, where
+\textit{n} is in the range 1 to 16. The \textit{param} argument specifies
+which parameter to retrieve. To determine if a joystick is connected,
+\textit{param} should be GLFW\_PRESENT, which will cause the function to
+return GL\_TRUE if the joystick is connected, or GL\_FALSE if it is not.
+To determine the number of axes or buttons that are supported by the
+joystick, \textit{param} should be GLFW\_AXES or GLFW\_BUTTONS,
+respectively.
+
+
+%-------------------------------------------------------------------------
+\subsection{Joystick position}
+To get the current axis positions of the joystick, the
+\textbf{glfwGetJoystickPos} is used:
+
+\begin{lstlisting}
+int glfwGetJoystickPos( int joy, float *pos, int numaxes )
+\end{lstlisting}
+
+As with \textbf{glfwGetJoystickParam}, the \textit{joy} argument
+specifies which joystick to retrieve information from. The
+\textit{numaxes} argument specifies how many axes to return, and the
+\textit{pos} argument specifies an array in which all the axis positions
+are stored. The function returns the actual number of axes that were
+returned, which could be less than \textit{numaxes} if the joystick does
+not support all the requested axes, or if the joystick is not connected.
+
+For instance, to get the position of the first two axes (the X and Y axes)
+of joystick 1, the following code can be used:
+
+\begin{lstlisting}
+float position[ 2 ];
+
+glfwGetJoystickPos( GLFW_JOYSTICK_1, position, 2 );
+\end{lstlisting}
+
+After this call, the first element of the \textit{position} array will
+hold the X axis position of the joystick, and the second element will hold
+the Y axis position. In this example we do not use the information about
+how many axes were really returned.
+
+The position of an axis can be in the range -1.0 to 1.0, where positive
+values represent right, forward or up directions, while negative values
+represent left, back or down directions. If a requested axis is not
+supported by the joystick, the corresponding array element will be set
+to zero. The same goes for the situation when the joystick is not
+connected (all axes are treated as unsupported).
+
+
+%-------------------------------------------------------------------------
+\subsection{Joystick buttons}
+A function similar to the \textbf{glfwGetJoystickPos} function is
+available for querying the state of joystick buttons, namely the
+\textbf{glfwGetJoystickButtons} function:
+
+\begin{lstlisting}
+int glfwGetJoystickButtons( int joy, unsigned char *buttons,
+ int numbuttons )
+\end{lstlisting}
+
+The function works just like the \textbf{glfwGetJoystickAxis} function,
+except that it returns the state of joystick buttons instead of axis
+positions. Each button in the array specified by the \textit{buttons}
+argument can be either GLFW\_PRESS or GLFW\_RELEASE, telling if the
+corresponding button is currently held down or not. Unsupported buttons
+will have the value GLFW\_RELEASE.
+
+
+%-------------------------------------------------------------------------
+% Timing
+%-------------------------------------------------------------------------
+\chapter{Timing}
+\thispagestyle{fancy}
+
+%-------------------------------------------------------------------------
+\section{High Resolution Timer}
+In most applications, it is useful to know exactly how much time has
+passed between point $A$ and point $B$ in a program. A typical situation
+is in a game, where you need to know how much time has passed between two
+rendered frames in order to calculate the correct movement and physics
+etc. Another example is when you want to benchmark a certain piece of
+code.
+
+\GLFW\ provides a high-resolution timer, which reports a double precision
+floating point value representing the number of seconds that have passed
+since \textbf{glfwInit} was called. The timer is accessed with the
+function \textbf{glfwGetTime}:
+
+\begin{lstlisting}
+double glfwGetTime( void )
+\end{lstlisting}
+
+The precision of the timer depends on which computer and operating
+system you are running, but it is almost guaranteed to be better than
+$10~ms$, and in most cases it is much better than $1~ms$ (on a modern PC
+you can get resolutions in the order of $1~ns$).
+
+It is possible to set the value of the high precision timer using the
+\textbf{glfwSetTime} function:
+
+\begin{lstlisting}
+void glfwSetTime( double time )
+\end{lstlisting}
+
+The argument \textit{time} is the time, in seconds, that the timer should
+be set to.
+
+
+%-------------------------------------------------------------------------
+% OpenGL Extension Support
+%-------------------------------------------------------------------------
+\chapter{OpenGL Extension Support}
+\thispagestyle{fancy}
+One of the benefits of \OpenGL\ is that it is extensible. Independent
+hardware vendors (IHVs) may include functionality in their \OpenGL\
+implementations that exceed that of the \OpenGL\ standard.
+
+An extension is defined by:
+
+\begin{enumerate}
+\item An extension name (e.g. GL\_ARB\_multitexture).
+\item New OpenGL tokens (e.g. GL\_TEXTURE1\_ARB).
+\item New OpenGL functions (e.g. \textbf{glActiveTextureARB}).
+\end{enumerate}
+
+A list of official extensions, together with their definitions, can be
+found at the \textit{OpenGL Extension Registry}
+(\url{http://oss.sgi.com/projects/ogl-sample/registry/}).
+
+To use a certain extension, the following steps must be performed:
+
+\begin{enumerate}
+\item A compile time check for the support of the extension.
+\item A run time check for the support of the extension.
+\item Fetch function pointers for the extended \OpenGL\ functions (done at
+ run time).
+\end{enumerate}
+
+How this is done using \GLFW\ is described in the following sections.
+Please note that this chapter covers some advanced topics, and is quite
+specific to the C programming language.
+
+
+%-------------------------------------------------------------------------
+\section{Compile Time Check}
+The compile time check is necessary to perform in order to know if the
+compiler include files have defined the necessary tokens. It is very easy
+to do. The include file \texttt{GL/gl.h} will define a constant with the
+same name as the extension, if all the extension tokens are defined. Here
+is an example of how to check for the extension GL\_ARB\_multitexture:
+
+\begin{lstlisting}
+#ifdef GL_ARB_multitexture
+ // Extension is supported by the include files
+#else
+ // Extension is not supported by the include files
+ // Update your file!
+#endif
+\end{lstlisting}
+
+
+%-------------------------------------------------------------------------
+\section{Runtime Check}
+Even if the compiler include files have defined all the necessary tokens,
+the target system may not support the extension (perhaps it has a
+different graphic card with a different \OpenGL\ implementation, or it has
+an older driver). That is why it is necessary to do a run time check for
+the extension support as well. This is done with the \GLFW\ function
+\textbf{glfwExtensionSupported}, which has the C syntax:
+
+\begin{lstlisting}
+int glfwExtensionSupported( const char *extension )
+\end{lstlisting}
+
+The argument \textit{extension} is a null terminated ISO~8859-1 string
+with the extension name. \textbf{glfwExtensionSupported} returns GL\_TRUE
+if the extension is supported, otherwise it returns GL\_FALSE.
+
+Let us extend the previous example of checking for support of the
+extension GL\_ARB\_multitexture. This time we add a run time check, and a
+variable which we set to GL\_TRUE if the extension is supported, or
+GL\_FALSE if it is not supported.
+
+\begin{lstlisting}
+int multitexture_supported;
+
+#ifdef GL_ARB_multitexture
+ // Check if extension is supported at run time
+ multitexture_supported =
+ glfwExtensionSupported( "GL_ARB_multitexture" );
+#else
+ // Extension is not supported by the include files
+ // Update your file!
+ multitexture_supported = GL_FALSE;
+#endif
+\end{lstlisting}
+
+Now it is easy to check for the extension within the program, simply do:
+
+\begin{lstlisting}
+ if( multitexture_supported )
+ {
+ // Use multi texturing
+ }
+ else
+ {
+ // Use some other solution (or fail)
+ }
+\end{lstlisting}
+
+
+%-------------------------------------------------------------------------
+\section{Fetching Function Pointers}
+Some extensions (not all) require the use of new \OpenGL\ functions, which
+are not necessarily defined by your link libraries. Thus it is necessary
+to get the function pointers dynamically at run time. This is done with
+the \GLFW\ function \textbf{glfwGetProcAddress}:
+
+\begin{lstlisting}
+void * glfwGetProcAddress( const char *procname )
+\end{lstlisting}
+
+The argument \textit{procname} is a null terminated ISO~8859-1 string
+holding the name of the \OpenGL\ function. \textbf{glfwGetProcAddress}
+returns the address to the function if the function is available,
+otherwise NULL is returned.
+
+Obviously, fetching the function pointer is trivial. For instance, if we
+want to obtain the pointer to \textbf{glActiveTextureARB}, we simply call:
+
+\begin{lstlisting}
+glActiveTextureARB = glfwGetProcAddress( "glActiveTextureARB" );
+\end{lstlisting}
+
+However, there are many possible naming and type definition conflicts
+involved with such an operation, which may result in compiler warnings or
+errors. My proposed solution is the following:
+
+\begin{itemize}
+\item Do not use the function name for the variable name. Use something
+ similar (perhaps with a prefix or suffix), and then use
+ \texttt{\#define} to map the function name to your variable.
+\item The standard type definition naming convention for function pointers
+ is \texttt{PFN\textit{xxxx}PROC}, where \texttt{\textit{xxxx}} is
+ the uppercase version of the function name (e.g.
+ \texttt{PFNGLACTIVETEXTUREARBPROC}). Either make sure that a
+ compatible \texttt{gl.h} and/or \texttt{glext.h} file is used by
+ your compiler and rely on it to do the type definitions for you, or
+ use a custom type definition naming convention (e.g.
+ \texttt{\textit{xxxx}\_T} or something) and do the type definitions
+ yourself.
+\end{itemize}
+
+Here is an example of how to do it (here we use our own function pointer
+type defintion):
+
+\begin{lstlisting}
+// Type definition of the function pointer
+typedef void (APIENTRY * GLACTIVETEXTUREARB_T) (GLenum texture);
+
+// Function pointer
+GLACTIVETEXTUREARB_T _ActiveTextureARB;
+#define glActiveTextureARB _ActiveTextureARB
+
+// Extension availability flag
+int multitexture_supported;
+
+#ifdef GL_ARB_multitexture
+ // Check if extension is supported at run time
+ if( glfwExtensionSupported( "GL_ARB_multitexture" ) )
+ {
+ // Get the function pointer
+ glActiveTextureARB = (GLACTIVETEXTUREARB_T)
+ glfwGetProcAddress( "glActiveTextureARB" );
+
+ multitexture_supported = GL_TRUE;
+ }
+ else
+ {
+ multitexture_supported = GL_FALSE;
+ }
+#else
+ // Extension is not supported by the include files
+ multitexture_supported = GL_FALSE;
+#endif
+\end{lstlisting}
+
+Please note that the code example is not 100\% complete. First of all,
+the GL\_ARB\_multitexture extension defines many more functions than the
+single function that the code example defines. Secondly, checking if an
+extension is supported using \textbf{glfwExtensionSupported} is not enough
+to ensure that the corresponding functions will be valid. You also need to
+check if the function pointers returned by \textbf{glfwGetProcAddress} are
+non-NULL values.
+
+
+%-------------------------------------------------------------------------
+\subsection{Function pointer type definitions}
+To make a function pointer type definition, you need to know the function
+prototype. This can often be found in the extension definitions (e.g. at
+the \textit{OpenGL Extension Registry}). All the functions that are
+defined for an extension are listed with their C prototype definitions
+under the section \textit{New Procedures and Functions} in the extension
+definition.
+
+For instance, if we look at the definition of the
+GL\_ARB\_texture\_compression extension, we find a list of new functions.
+One of the functions looks like this:
+
+\begin{lstlisting}
+void GetCompressedTexImageARB(enum target, int lod, void *img);
+\end{lstlisting}
+
+Like in most official \OpenGL\ documentation, all the \texttt{GL} and
+\texttt{gl} prefixes have been left out. In other words, the real function
+prototype would look like this:
+
+\begin{lstlisting}
+void glGetCompressedTexImageARB(GLenum target, GLint lod, void *img);
+\end{lstlisting}
+
+All we have to do to turn this prototype definition into a function
+pointer type definition, is to replace the function name with
+\texttt{(APIENTRY * \textit{xxxx}\_T)}, where \textit{xxxx} is the
+uppercase version of the name (according to the proposed naming
+convention). The keyword \texttt{APIENTRY} is needed to be compatible
+between different platforms. The \GLFW\ include file \texttt{GL/glfw.h}
+always makes sure that \texttt{APIENTRY} is properly defined, regardless
+of which platform the program is compiled on.
+
+In other words, for the function \textbf{glGetCompressedTexImageARB} we
+get:
+
+\begin{lstlisting}
+typedef void (APIENTRY * GLGETCOMPRESSEDTEXIMAGEARB_T)
+ (GLenum target, GLint level, void *img);
+\end{lstlisting}
+
+
+
+%-------------------------------------------------------------------------
+% Index
+%-------------------------------------------------------------------------
+% ...
+
+\end{document}
diff --git a/docs/readme.txt b/docs/readme.txt
new file mode 100644
index 00000000..f34521a2
--- /dev/null
+++ b/docs/readme.txt
@@ -0,0 +1,52 @@
+Introduction
+------------
+
+The GLFW documentation is written in LaTeX. Besides being powerful, LaTeX is
+also very attractive since all the necessary tools for dealing with LaTeX
+documentation are both free and ported to a wide variety of platforms. Another
+advantage is that the LaTeX files are written in plain text, which means that
+version control systems such as CVS handle them perfectly without having to
+treat the documents as binary files.
+
+
+The documents
+-------------
+
+There are two main documents:
+
+ glfwrm.tex - The GLFW Reference Manual
+ glfwug.tex - The GLFW Users Guide
+
+In addition, there is a common LaTeX style file that sets up things
+such as page formatting and useful macros:
+
+ glfwdoc.sty - Common GLFW document styles and macros
+
+
+Requirements
+------------
+
+Of course you need LaTeX installed on your system in order to compile the GLFW
+documentation. If you are using a Unix-like operating system, then your
+package system most likely has a version of LaTeX adapted for your system. If
+not, the easiest way to get a full LaTeX system is to download/get the TeXLive
+CD from http://www.tug.org/texlive/. It has all the necessary software for
+Windows, Mac OS X and most popular Unix-like operating systems.
+
+A number of LaTeX packages have to be installed in order to compile the
+GLFW documentation successfully:
+
+ color
+ fancyhdr
+ hyperref
+ lastpage
+ listings
+ needspace
+ textcase
+ times
+ titling
+
+These packages are all available on the TeXLive CD. Just make sure that
+you have checked all these packages when installing TeXLive, or get them
+in some other way if you do not have the TeXLive CD.
+
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
new file mode 100644
index 00000000..a6282a14
--- /dev/null
+++ b/examples/CMakeLists.txt
@@ -0,0 +1,37 @@
+# This line is used to link with static libraries
+# Note that the library list should be updated to be obtained from
+# the main CMakeLists.txt
+link_libraries(libglfwStatic ${GLFW_LIBRARIES} ${OPENGL_glu_LIBRARY})
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include ${OPENGL_INCLUDE_DIR})
+
+add_executable(listmodes listmodes.c)
+
+if(APPLE)
+ # Set fancy names for bundles
+ add_executable(Boing MACOSX_BUNDLE boing.c)
+ add_executable(Gears MACOSX_BUNDLE gears.c)
+ add_executable("Split View" MACOSX_BUNDLE splitview.c)
+ add_executable(Triangle MACOSX_BUNDLE triangle.c)
+ add_executable(Wave MACOSX_BUNDLE wave.c)
+else(APPLE)
+ # Set boring names for executables
+ add_executable(boing WIN32 boing.c)
+ add_executable(gears WIN32 gears.c)
+ add_executable(splitview WIN32 splitview.c)
+ add_executable(triangle WIN32 triangle.c)
+ add_executable(wave WIN32 wave.c)
+endif(APPLE)
+
+if(MSVC)
+ # Tell MSVC to use main instead of WinMain for Windows subsystem executables
+ set_target_properties(boing gears splitview triangle wave PROPERTIES LINK_FLAGS "/ENTRY:mainCRTStartup")
+endif(MSVC)
+
+if(CYGWIN)
+ # Set cross-compile and subsystem compile and link flags
+ set_target_properties(boing gears listmodes splitview triangle wave PROPERTIES COMPILE_FLAGS "-mno-cygwin")
+ set_target_properties(boing gears splitview triangle wave PROPERTIES LINK_FLAGS "-mno-cygwin -mwindows")
+ set_target_properties(listmodes PROPERTIES LINK_FLAGS "-mno-cygwin -mconsole")
+endif(CYGWIN)
+
diff --git a/examples/boing.c b/examples/boing.c
new file mode 100644
index 00000000..451445b0
--- /dev/null
+++ b/examples/boing.c
@@ -0,0 +1,615 @@
+/*****************************************************************************
+ * Title: GLBoing
+ * Desc: Tribute to Amiga Boing.
+ * Author: Jim Brooks
+ * Original Amiga authors were R.J. Mical and Dale Luck.
+ * GLFW conversion by Marcus Geelnard
+ * Notes: - 360' = 2*PI [radian]
+ *
+ * - Distances between objects are created by doing a relative
+ * Z translations.
+ *
+ * - Although OpenGL enticingly supports alpha-blending,
+ * the shadow of the original Boing didn't affect the color
+ * of the grid.
+ *
+ * - [Marcus] Changed timing scheme from interval driven to frame-
+ * time based animation steps (which results in much smoother
+ * movement)
+ *
+ * History of Amiga Boing:
+ *
+ * Boing was demonstrated on the prototype Amiga (codenamed "Lorraine") in
+ * 1985. According to legend, it was written ad-hoc in one night by
+ * R. J. Mical and Dale Luck. Because the bouncing ball animation was so fast
+ * and smooth, attendees did not believe the Amiga prototype was really doing
+ * the rendering. Suspecting a trick, they began looking around the booth for
+ * a hidden computer or VCR.
+ *****************************************************************************/
+
+#include
+#include
+#include
+#include
+
+
+/*****************************************************************************
+ * Various declarations and macros
+ *****************************************************************************/
+
+/* Prototypes */
+void init( void );
+void display( void );
+void reshape( int w, int h );
+void DrawBoingBall( void );
+void BounceBall( double dt );
+void DrawBoingBallBand( GLfloat long_lo, GLfloat long_hi );
+void DrawGrid( void );
+
+#define RADIUS 70.f
+#define STEP_LONGITUDE 22.5f /* 22.5 makes 8 bands like original Boing */
+#define STEP_LATITUDE 22.5f
+
+#define DIST_BALL (RADIUS * 2.f + RADIUS * 0.1f)
+
+#define VIEW_SCENE_DIST (DIST_BALL * 3.f + 200.f)/* distance from viewer to middle of boing area */
+#define GRID_SIZE (RADIUS * 4.5f) /* length (width) of grid */
+#define BOUNCE_HEIGHT (RADIUS * 2.1f)
+#define BOUNCE_WIDTH (RADIUS * 2.1f)
+
+#define SHADOW_OFFSET_X -20.f
+#define SHADOW_OFFSET_Y 10.f
+#define SHADOW_OFFSET_Z 0.f
+
+#define WALL_L_OFFSET 0.f
+#define WALL_R_OFFSET 5.f
+
+/* Animation speed (50.0 mimics the original GLUT demo speed) */
+#define ANIMATION_SPEED 50.f
+
+/* Maximum allowed delta time per physics iteration */
+#define MAX_DELTA_T 0.02f
+
+/* Draw ball, or its shadow */
+typedef enum { DRAW_BALL, DRAW_BALL_SHADOW } DRAW_BALL_ENUM;
+
+/* Vertex type */
+typedef struct {float x; float y; float z;} vertex_t;
+
+/* Global vars */
+GLfloat deg_rot_y = 0.f;
+GLfloat deg_rot_y_inc = 2.f;
+GLfloat ball_x = -RADIUS;
+GLfloat ball_y = -RADIUS;
+GLfloat ball_x_inc = 1.f;
+GLfloat ball_y_inc = 2.f;
+DRAW_BALL_ENUM drawBallHow;
+double t;
+double t_old = 0.f;
+double dt;
+
+/* Random number generator */
+#ifndef RAND_MAX
+ #define RAND_MAX 4095
+#endif
+
+/* PI */
+#ifndef M_PI
+ #define M_PI 3.1415926535897932384626433832795
+#endif
+
+
+/*****************************************************************************
+ * Truncate a degree.
+ *****************************************************************************/
+GLfloat TruncateDeg( GLfloat deg )
+{
+ if ( deg >= 360.f )
+ return (deg - 360.f);
+ else
+ return deg;
+}
+
+/*****************************************************************************
+ * Convert a degree (360-based) into a radian.
+ * 360' = 2 * PI
+ *****************************************************************************/
+double deg2rad( double deg )
+{
+ return deg / 360 * (2 * M_PI);
+}
+
+/*****************************************************************************
+ * 360' sin().
+ *****************************************************************************/
+double sin_deg( double deg )
+{
+ return sin( deg2rad( deg ) );
+}
+
+/*****************************************************************************
+ * 360' cos().
+ *****************************************************************************/
+double cos_deg( double deg )
+{
+ return cos( deg2rad( deg ) );
+}
+
+/*****************************************************************************
+ * Compute a cross product (for a normal vector).
+ *
+ * c = a x b
+ *****************************************************************************/
+void CrossProduct( vertex_t a, vertex_t b, vertex_t c, vertex_t *n )
+{
+ GLfloat u1, u2, u3;
+ GLfloat v1, v2, v3;
+
+ u1 = b.x - a.x;
+ u2 = b.y - a.y;
+ u3 = b.y - a.z;
+
+ v1 = c.x - a.x;
+ v2 = c.y - a.y;
+ v3 = c.z - a.z;
+
+ n->x = u2 * v3 - v2 * v3;
+ n->y = u3 * v1 - v3 * u1;
+ n->z = u1 * v2 - v1 * u2;
+}
+
+/*****************************************************************************
+ * Calculate the angle to be passed to gluPerspective() so that a scene
+ * is visible. This function originates from the OpenGL Red Book.
+ *
+ * Parms : size
+ * The size of the segment when the angle is intersected at "dist"
+ * (ie at the outermost edge of the angle of vision).
+ *
+ * dist
+ * Distance from viewpoint to scene.
+ *****************************************************************************/
+GLfloat PerspectiveAngle( GLfloat size,
+ GLfloat dist )
+{
+ GLfloat radTheta, degTheta;
+
+ radTheta = 2.f * (GLfloat) atan2( size / 2.f, dist );
+ degTheta = (180.f * radTheta) / (GLfloat) M_PI;
+ return degTheta;
+}
+
+
+
+#define BOING_DEBUG 0
+
+
+/*****************************************************************************
+ * init()
+ *****************************************************************************/
+void init( void )
+{
+ /*
+ * Clear background.
+ */
+ glClearColor( 0.55f, 0.55f, 0.55f, 0.f );
+
+ glShadeModel( GL_FLAT );
+}
+
+
+/*****************************************************************************
+ * display()
+ *****************************************************************************/
+void display(void)
+{
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ glPushMatrix();
+
+ drawBallHow = DRAW_BALL_SHADOW;
+ DrawBoingBall();
+
+ DrawGrid();
+
+ drawBallHow = DRAW_BALL;
+ DrawBoingBall();
+
+ glPopMatrix();
+ glFlush();
+}
+
+
+/*****************************************************************************
+ * reshape()
+ *****************************************************************************/
+void reshape( int w, int h )
+{
+ glViewport( 0, 0, (GLsizei)w, (GLsizei)h );
+
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+
+ gluPerspective( PerspectiveAngle( RADIUS * 2, 200 ),
+ (GLfloat)w / (GLfloat)h,
+ 1.0,
+ VIEW_SCENE_DIST );
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ gluLookAt( 0.0, 0.0, VIEW_SCENE_DIST,/* eye */
+ 0.0, 0.0, 0.0, /* center of vision */
+ 0.0, -1.0, 0.0 ); /* up vector */
+}
+
+
+/*****************************************************************************
+ * Draw the Boing ball.
+ *
+ * The Boing ball is sphere in which each facet is a rectangle.
+ * Facet colors alternate between red and white.
+ * The ball is built by stacking latitudinal circles. Each circle is composed
+ * of a widely-separated set of points, so that each facet is noticably large.
+ *****************************************************************************/
+void DrawBoingBall( void )
+{
+ GLfloat lon_deg; /* degree of longitude */
+ double dt_total, dt2;
+
+ glPushMatrix();
+ glMatrixMode( GL_MODELVIEW );
+
+ /*
+ * Another relative Z translation to separate objects.
+ */
+ glTranslatef( 0.0, 0.0, DIST_BALL );
+
+ /* Update ball position and rotation (iterate if necessary) */
+ dt_total = dt;
+ while( dt_total > 0.0 )
+ {
+ dt2 = dt_total > MAX_DELTA_T ? MAX_DELTA_T : dt_total;
+ dt_total -= dt2;
+ BounceBall( dt2 );
+ deg_rot_y = TruncateDeg( deg_rot_y + deg_rot_y_inc*((float)dt2*ANIMATION_SPEED) );
+ }
+
+ /* Set ball position */
+ glTranslatef( ball_x, ball_y, 0.0 );
+
+ /*
+ * Offset the shadow.
+ */
+ if ( drawBallHow == DRAW_BALL_SHADOW )
+ {
+ glTranslatef( SHADOW_OFFSET_X,
+ SHADOW_OFFSET_Y,
+ SHADOW_OFFSET_Z );
+ }
+
+ /*
+ * Tilt the ball.
+ */
+ glRotatef( -20.0, 0.0, 0.0, 1.0 );
+
+ /*
+ * Continually rotate ball around Y axis.
+ */
+ glRotatef( deg_rot_y, 0.0, 1.0, 0.0 );
+
+ /*
+ * Set OpenGL state for Boing ball.
+ */
+ glCullFace( GL_FRONT );
+ glEnable( GL_CULL_FACE );
+ glEnable( GL_NORMALIZE );
+
+ /*
+ * Build a faceted latitude slice of the Boing ball,
+ * stepping same-sized vertical bands of the sphere.
+ */
+ for ( lon_deg = 0;
+ lon_deg < 180;
+ lon_deg += STEP_LONGITUDE )
+ {
+ /*
+ * Draw a latitude circle at this longitude.
+ */
+ DrawBoingBallBand( lon_deg,
+ lon_deg + STEP_LONGITUDE );
+ }
+
+ glPopMatrix();
+
+ return;
+}
+
+
+/*****************************************************************************
+ * Bounce the ball.
+ *****************************************************************************/
+void BounceBall( double dt )
+{
+ GLfloat sign;
+ GLfloat deg;
+
+ /* Bounce on walls */
+ if ( ball_x > (BOUNCE_WIDTH/2 + WALL_R_OFFSET ) )
+ {
+ ball_x_inc = -0.5f - 0.75f * (GLfloat)rand() / (GLfloat)RAND_MAX;
+ deg_rot_y_inc = -deg_rot_y_inc;
+ }
+ if ( ball_x < -(BOUNCE_HEIGHT/2 + WALL_L_OFFSET) )
+ {
+ ball_x_inc = 0.5f + 0.75f * (GLfloat)rand() / (GLfloat)RAND_MAX;
+ deg_rot_y_inc = -deg_rot_y_inc;
+ }
+
+ /* Bounce on floor / roof */
+ if ( ball_y > BOUNCE_HEIGHT/2 )
+ {
+ ball_y_inc = -0.75f - 1.f * (GLfloat)rand() / (GLfloat)RAND_MAX;
+ }
+ if ( ball_y < -BOUNCE_HEIGHT/2*0.85 )
+ {
+ ball_y_inc = 0.75f + 1.f * (GLfloat)rand() / (GLfloat)RAND_MAX;
+ }
+
+ /* Update ball position */
+ ball_x += ball_x_inc * ((float)dt*ANIMATION_SPEED);
+ ball_y += ball_y_inc * ((float)dt*ANIMATION_SPEED);
+
+ /*
+ * Simulate the effects of gravity on Y movement.
+ */
+ if ( ball_y_inc < 0 ) sign = -1.0; else sign = 1.0;
+
+ deg = (ball_y + BOUNCE_HEIGHT/2) * 90 / BOUNCE_HEIGHT;
+ if ( deg > 80 ) deg = 80;
+ if ( deg < 10 ) deg = 10;
+
+ ball_y_inc = sign * 4.f * (float) sin_deg( deg );
+}
+
+
+/*****************************************************************************
+ * Draw a faceted latitude band of the Boing ball.
+ *
+ * Parms: long_lo, long_hi
+ * Low and high longitudes of slice, resp.
+ *****************************************************************************/
+void DrawBoingBallBand( GLfloat long_lo,
+ GLfloat long_hi )
+{
+ vertex_t vert_ne; /* "ne" means south-east, so on */
+ vertex_t vert_nw;
+ vertex_t vert_sw;
+ vertex_t vert_se;
+ vertex_t vert_norm;
+ GLfloat lat_deg;
+ static int colorToggle = 0;
+
+ /*
+ * Iterate thru the points of a latitude circle.
+ * A latitude circle is a 2D set of X,Z points.
+ */
+ for ( lat_deg = 0;
+ lat_deg <= (360 - STEP_LATITUDE);
+ lat_deg += STEP_LATITUDE )
+ {
+ /*
+ * Color this polygon with red or white.
+ */
+ if ( colorToggle )
+ glColor3f( 0.8f, 0.1f, 0.1f );
+ else
+ glColor3f( 0.95f, 0.95f, 0.95f );
+#if 0
+ if ( lat_deg >= 180 )
+ if ( colorToggle )
+ glColor3f( 0.1f, 0.8f, 0.1f );
+ else
+ glColor3f( 0.5f, 0.5f, 0.95f );
+#endif
+ colorToggle = ! colorToggle;
+
+ /*
+ * Change color if drawing shadow.
+ */
+ if ( drawBallHow == DRAW_BALL_SHADOW )
+ glColor3f( 0.35f, 0.35f, 0.35f );
+
+ /*
+ * Assign each Y.
+ */
+ vert_ne.y = vert_nw.y = (float) cos_deg(long_hi) * RADIUS;
+ vert_sw.y = vert_se.y = (float) cos_deg(long_lo) * RADIUS;
+
+ /*
+ * Assign each X,Z with sin,cos values scaled by latitude radius indexed by longitude.
+ * Eg, long=0 and long=180 are at the poles, so zero scale is sin(longitude),
+ * while long=90 (sin(90)=1) is at equator.
+ */
+ vert_ne.x = (float) cos_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
+ vert_se.x = (float) cos_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo ));
+ vert_nw.x = (float) cos_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
+ vert_sw.x = (float) cos_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo ));
+
+ vert_ne.z = (float) sin_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
+ vert_se.z = (float) sin_deg( lat_deg ) * (RADIUS * (float) sin_deg( long_lo ));
+ vert_nw.z = (float) sin_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo + STEP_LONGITUDE ));
+ vert_sw.z = (float) sin_deg( lat_deg + STEP_LATITUDE ) * (RADIUS * (float) sin_deg( long_lo ));
+
+ /*
+ * Draw the facet.
+ */
+ glBegin( GL_POLYGON );
+
+ CrossProduct( vert_ne, vert_nw, vert_sw, &vert_norm );
+ glNormal3f( vert_norm.x, vert_norm.y, vert_norm.z );
+
+ glVertex3f( vert_ne.x, vert_ne.y, vert_ne.z );
+ glVertex3f( vert_nw.x, vert_nw.y, vert_nw.z );
+ glVertex3f( vert_sw.x, vert_sw.y, vert_sw.z );
+ glVertex3f( vert_se.x, vert_se.y, vert_se.z );
+
+ glEnd();
+
+#if BOING_DEBUG
+ printf( "----------------------------------------------------------- \n" );
+ printf( "lat = %f long_lo = %f long_hi = %f \n", lat_deg, long_lo, long_hi );
+ printf( "vert_ne x = %.8f y = %.8f z = %.8f \n", vert_ne.x, vert_ne.y, vert_ne.z );
+ printf( "vert_nw x = %.8f y = %.8f z = %.8f \n", vert_nw.x, vert_nw.y, vert_nw.z );
+ printf( "vert_se x = %.8f y = %.8f z = %.8f \n", vert_se.x, vert_se.y, vert_se.z );
+ printf( "vert_sw x = %.8f y = %.8f z = %.8f \n", vert_sw.x, vert_sw.y, vert_sw.z );
+#endif
+
+ }
+
+ /*
+ * Toggle color so that next band will opposite red/white colors than this one.
+ */
+ colorToggle = ! colorToggle;
+
+ /*
+ * This circular band is done.
+ */
+ return;
+}
+
+
+/*****************************************************************************
+ * Draw the purple grid of lines, behind the Boing ball.
+ * When the Workbench is dropped to the bottom, Boing shows 12 rows.
+ *****************************************************************************/
+void DrawGrid( void )
+{
+ int row, col;
+ const int rowTotal = 12; /* must be divisible by 2 */
+ const int colTotal = rowTotal; /* must be same as rowTotal */
+ const GLfloat widthLine = 2.0; /* should be divisible by 2 */
+ const GLfloat sizeCell = GRID_SIZE / rowTotal;
+ const GLfloat z_offset = -40.0;
+ GLfloat xl, xr;
+ GLfloat yt, yb;
+
+ glPushMatrix();
+ glDisable( GL_CULL_FACE );
+
+ /*
+ * Another relative Z translation to separate objects.
+ */
+ glTranslatef( 0.0, 0.0, DIST_BALL );
+
+ /*
+ * Draw vertical lines (as skinny 3D rectangles).
+ */
+ for ( col = 0; col <= colTotal; col++ )
+ {
+ /*
+ * Compute co-ords of line.
+ */
+ xl = -GRID_SIZE / 2 + col * sizeCell;
+ xr = xl + widthLine;
+
+ yt = GRID_SIZE / 2;
+ yb = -GRID_SIZE / 2 - widthLine;
+
+ glBegin( GL_POLYGON );
+
+ glColor3f( 0.6f, 0.1f, 0.6f ); /* purple */
+
+ glVertex3f( xr, yt, z_offset ); /* NE */
+ glVertex3f( xl, yt, z_offset ); /* NW */
+ glVertex3f( xl, yb, z_offset ); /* SW */
+ glVertex3f( xr, yb, z_offset ); /* SE */
+
+ glEnd();
+ }
+
+ /*
+ * Draw horizontal lines (as skinny 3D rectangles).
+ */
+ for ( row = 0; row <= rowTotal; row++ )
+ {
+ /*
+ * Compute co-ords of line.
+ */
+ yt = GRID_SIZE / 2 - row * sizeCell;
+ yb = yt - widthLine;
+
+ xl = -GRID_SIZE / 2;
+ xr = GRID_SIZE / 2 + widthLine;
+
+ glBegin( GL_POLYGON );
+
+ glColor3f( 0.6f, 0.1f, 0.6f ); /* purple */
+
+ glVertex3f( xr, yt, z_offset ); /* NE */
+ glVertex3f( xl, yt, z_offset ); /* NW */
+ glVertex3f( xl, yb, z_offset ); /* SW */
+ glVertex3f( xr, yb, z_offset ); /* SE */
+
+ glEnd();
+ }
+
+ glPopMatrix();
+
+ return;
+}
+
+
+/*======================================================================*
+ * main()
+ *======================================================================*/
+
+int main( void )
+{
+ int running;
+
+ /* Init GLFW */
+ if( !glfwInit() )
+ {
+ fprintf( stderr, "Failed to initialize GLFW\n" );
+ exit( EXIT_FAILURE );
+ }
+
+ if( !glfwOpenWindow( 400,400, 0,0,0,0, 16,0, GLFW_WINDOW ) )
+ {
+ fprintf( stderr, "Failed to open GLFW window\n" );
+ glfwTerminate();
+ exit( EXIT_FAILURE );
+ }
+
+ glfwSetWindowTitle( "Boing (classic Amiga demo)" );
+ glfwSetWindowSizeCallback( reshape );
+ glfwEnable( GLFW_STICKY_KEYS );
+ glfwSwapInterval( 1 );
+ glfwSetTime( 0.0 );
+
+ init();
+
+ /* Main loop */
+ do
+ {
+ /* Timing */
+ t = glfwGetTime();
+ dt = t - t_old;
+ t_old = t;
+
+ /* Draw one frame */
+ display();
+
+ /* Swap buffers */
+ glfwSwapBuffers();
+
+ /* Check if we are still running */
+ running = !glfwGetKey( GLFW_KEY_ESC ) &&
+ glfwGetWindowParam( GLFW_OPENED );
+ }
+ while( running );
+
+ glfwTerminate();
+ exit( EXIT_SUCCESS );
+}
+
diff --git a/examples/gears.c b/examples/gears.c
new file mode 100644
index 00000000..5ad484db
--- /dev/null
+++ b/examples/gears.c
@@ -0,0 +1,373 @@
+/*
+ * 3-D gear wheels. This program is in the public domain.
+ *
+ * Command line options:
+ * -info print GL implementation information
+ * -exit automatically exit after 30 seconds
+ *
+ *
+ * Brian Paul
+ *
+ *
+ * Marcus Geelnard:
+ * - Conversion to GLFW
+ * - Time based rendering (frame rate independent)
+ * - Slightly modified camera that should work better for stereo viewing
+ *
+ *
+ * Camilla Berglund:
+ * - Removed FPS counter (this is not a benchmark)
+ * - Added a few comments
+ * - Enabled vsync
+ */
+
+
+#include
+#include
+#include
+#include
+#include
+
+#ifndef M_PI
+#define M_PI 3.141592654
+#endif
+
+/* The program exits when this is zero.
+ */
+static int running = 1;
+
+/* If non-zero, the program exits after that many seconds
+ */
+static int autoexit = 0;
+
+/**
+
+ Draw a gear wheel. You'll probably want to call this function when
+ building a display list since we do a lot of trig here.
+
+ Input: inner_radius - radius of hole at center
+ outer_radius - radius at center of teeth
+ width - width of gear teeth - number of teeth
+ tooth_depth - depth of tooth
+
+ **/
+
+static void
+gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+ GLint teeth, GLfloat tooth_depth)
+{
+ GLint i;
+ GLfloat r0, r1, r2;
+ GLfloat angle, da;
+ GLfloat u, v, len;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.f;
+ r2 = outer_radius + tooth_depth / 2.f;
+
+ da = 2.f * (float) M_PI / teeth / 4.f;
+
+ glShadeModel(GL_FLAT);
+
+ glNormal3f(0.f, 0.f, 1.f);
+
+ /* draw front face */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.f * (float) M_PI / teeth;
+ glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), width * 0.5f);
+ glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), width * 0.5f);
+ if (i < teeth) {
+ glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), width * 0.5f);
+ glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), width * 0.5f);
+ }
+ }
+ glEnd();
+
+ /* draw front sides of teeth */
+ glBegin(GL_QUADS);
+ da = 2.f * (float) M_PI / teeth / 4.f;
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.f * (float) M_PI / teeth;
+
+ glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), width * 0.5f);
+ glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), width * 0.5f);
+ glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), width * 0.5f);
+ glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), width * 0.5f);
+ }
+ glEnd();
+
+ glNormal3f(0.0, 0.0, -1.0);
+
+ /* draw back face */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.f * (float) M_PI / teeth;
+ glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), -width * 0.5f);
+ glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), -width * 0.5f);
+ if (i < teeth) {
+ glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), -width * 0.5f);
+ glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), -width * 0.5f);
+ }
+ }
+ glEnd();
+
+ /* draw back sides of teeth */
+ glBegin(GL_QUADS);
+ da = 2.f * (float) M_PI / teeth / 4.f;
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.f * (float) M_PI / teeth;
+
+ glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), -width * 0.5f);
+ glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), -width * 0.5f);
+ glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), -width * 0.5f);
+ glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), -width * 0.5f);
+ }
+ glEnd();
+
+ /* draw outward faces of teeth */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.f * (float) M_PI / teeth;
+
+ glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), width * 0.5f);
+ glVertex3f(r1 * (float) cos(angle), r1 * (float) sin(angle), -width * 0.5f);
+ u = r2 * (float) cos(angle + da) - r1 * (float) cos(angle);
+ v = r2 * (float) sin(angle + da) - r1 * (float) sin(angle);
+ len = (float) sqrt(u * u + v * v);
+ u /= len;
+ v /= len;
+ glNormal3f(v, -u, 0.0);
+ glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), width * 0.5f);
+ glVertex3f(r2 * (float) cos(angle + da), r2 * (float) sin(angle + da), -width * 0.5f);
+ glNormal3f((float) cos(angle), (float) sin(angle), 0.f);
+ glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), width * 0.5f);
+ glVertex3f(r2 * (float) cos(angle + 2 * da), r2 * (float) sin(angle + 2 * da), -width * 0.5f);
+ u = r1 * (float) cos(angle + 3 * da) - r2 * (float) cos(angle + 2 * da);
+ v = r1 * (float) sin(angle + 3 * da) - r2 * (float) sin(angle + 2 * da);
+ glNormal3f(v, -u, 0.f);
+ glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), width * 0.5f);
+ glVertex3f(r1 * (float) cos(angle + 3 * da), r1 * (float) sin(angle + 3 * da), -width * 0.5f);
+ glNormal3f((float) cos(angle), (float) sin(angle), 0.f);
+ }
+
+ glVertex3f(r1 * (float) cos(0), r1 * (float) sin(0), width * 0.5f);
+ glVertex3f(r1 * (float) cos(0), r1 * (float) sin(0), -width * 0.5f);
+
+ glEnd();
+
+ glShadeModel(GL_SMOOTH);
+
+ /* draw inside radius cylinder */
+ glBegin(GL_QUAD_STRIP);
+ for (i = 0; i <= teeth; i++) {
+ angle = i * 2.f * (float) M_PI / teeth;
+ glNormal3f(-(float) cos(angle), -(float) sin(angle), 0.f);
+ glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), -width * 0.5f);
+ glVertex3f(r0 * (float) cos(angle), r0 * (float) sin(angle), width * 0.5f);
+ }
+ glEnd();
+
+}
+
+
+static GLfloat view_rotx = 20.f, view_roty = 30.f, view_rotz = 0.f;
+static GLint gear1, gear2, gear3;
+static GLfloat angle = 0.f;
+
+/* OpenGL draw function & timing */
+static void draw(void)
+{
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glPushMatrix();
+ glRotatef(view_rotx, 1.0, 0.0, 0.0);
+ glRotatef(view_roty, 0.0, 1.0, 0.0);
+ glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+ glPushMatrix();
+ glTranslatef(-3.0, -2.0, 0.0);
+ glRotatef(angle, 0.0, 0.0, 1.0);
+ glCallList(gear1);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(3.1f, -2.f, 0.f);
+ glRotatef(-2.f * angle - 9.f, 0.f, 0.f, 1.f);
+ glCallList(gear2);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef(-3.1f, 4.2f, 0.f);
+ glRotatef(-2.f * angle - 25.f, 0.f, 0.f, 1.f);
+ glCallList(gear3);
+ glPopMatrix();
+
+ glPopMatrix();
+}
+
+
+/* update animation parameters */
+static void animate(void)
+{
+ angle = 100.f * (float) glfwGetTime();
+}
+
+
+/* change view angle, exit upon ESC */
+void key( int k, int action )
+{
+ if( action != GLFW_PRESS ) return;
+
+ switch (k) {
+ case 'Z':
+ if( glfwGetKey( GLFW_KEY_LSHIFT ) )
+ view_rotz -= 5.0;
+ else
+ view_rotz += 5.0;
+ break;
+ case GLFW_KEY_ESC:
+ running = 0;
+ break;
+ case GLFW_KEY_UP:
+ view_rotx += 5.0;
+ break;
+ case GLFW_KEY_DOWN:
+ view_rotx -= 5.0;
+ break;
+ case GLFW_KEY_LEFT:
+ view_roty += 5.0;
+ break;
+ case GLFW_KEY_RIGHT:
+ view_roty -= 5.0;
+ break;
+ default:
+ return;
+ }
+}
+
+
+/* new window size */
+void reshape( int width, int height )
+{
+ GLfloat h = (GLfloat) height / (GLfloat) width;
+ GLfloat xmax, znear, zfar;
+
+ znear = 5.0f;
+ zfar = 30.0f;
+ xmax = znear * 0.5f;
+
+ glViewport( 0, 0, (GLint) width, (GLint) height );
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glFrustum( -xmax, xmax, -xmax*h, xmax*h, znear, zfar );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ glTranslatef( 0.0, 0.0, -20.0 );
+}
+
+
+/* program & OpenGL initialization */
+static void init(int argc, char *argv[])
+{
+ static GLfloat pos[4] = {5.f, 5.f, 10.f, 0.f};
+ static GLfloat red[4] = {0.8f, 0.1f, 0.f, 1.f};
+ static GLfloat green[4] = {0.f, 0.8f, 0.2f, 1.f};
+ static GLfloat blue[4] = {0.2f, 0.2f, 1.f, 1.f};
+ GLint i;
+
+ glLightfv(GL_LIGHT0, GL_POSITION, pos);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_DEPTH_TEST);
+
+ /* make the gears */
+ gear1 = glGenLists(1);
+ glNewList(gear1, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+ gear(1.f, 4.f, 1.f, 20, 0.7f);
+ glEndList();
+
+ gear2 = glGenLists(1);
+ glNewList(gear2, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+ gear(0.5f, 2.f, 2.f, 10, 0.7f);
+ glEndList();
+
+ gear3 = glGenLists(1);
+ glNewList(gear3, GL_COMPILE);
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
+ gear(1.3f, 2.f, 0.5f, 10, 0.7f);
+ glEndList();
+
+ glEnable(GL_NORMALIZE);
+
+ for ( i=1; i
+#include
+
+// Maximum number of modes that we want to list
+#define MAX_NUM_MODES 400
+
+
+//========================================================================
+// main()
+//========================================================================
+
+int main( void )
+{
+ GLFWvidmode dtmode, modes[ MAX_NUM_MODES ];
+ int modecount, i;
+
+ // Initialize GLFW
+ if( !glfwInit() )
+ {
+ return 0;
+ }
+
+ // Show desktop video mode
+ glfwGetDesktopMode( &dtmode );
+ printf( "Desktop mode: %d x %d x %d\n\n",
+ dtmode.Width, dtmode.Height, dtmode.RedBits +
+ dtmode.GreenBits + dtmode.BlueBits );
+
+ // List available video modes
+ modecount = glfwGetVideoModes( modes, MAX_NUM_MODES );
+ printf( "Available modes:\n" );
+ for( i = 0; i < modecount; i ++ )
+ {
+ printf( "%3d: %d x %d x %d\n", i,
+ modes[i].Width, modes[i].Height, modes[i].RedBits +
+ modes[i].GreenBits + modes[i].BlueBits );
+ }
+
+ // Terminate GLFW
+ glfwTerminate();
+
+ return 0;
+}
diff --git a/examples/mipmaps.c b/examples/mipmaps.c
new file mode 100644
index 00000000..59bbef2e
--- /dev/null
+++ b/examples/mipmaps.c
@@ -0,0 +1,122 @@
+//========================================================================
+// This is an example program for the GLFW library
+//
+// It shows texture loading with mipmap generation and rendering with
+// trilienar texture filtering
+//========================================================================
+
+#include
+#include
+
+#include
+
+int main( void )
+{
+ int width, height, x;
+ double time;
+ GLboolean running;
+ GLuint textureID;
+ char* texturePath = "mipmaps.tga";
+
+ // Initialise GLFW
+ if( !glfwInit() )
+ {
+ fprintf( stderr, "Failed to initialize GLFW\n" );
+ exit( EXIT_FAILURE );
+ }
+
+ // Open OpenGL window
+ if( !glfwOpenWindow( 640, 480, 0,0,0,0, 0,0, GLFW_WINDOW ) )
+ {
+ fprintf( stderr, "Failed to open GLFW window\n" );
+ glfwTerminate();
+ exit( EXIT_FAILURE );
+ }
+
+ glfwSetWindowTitle( "Trilinear interpolation" );
+
+ // Enable sticky keys
+ glfwEnable( GLFW_STICKY_KEYS );
+
+ // Enable vertical sync (on cards that support it)
+ glfwSwapInterval( 1 );
+
+ // Generate and bind our texture ID
+ glGenTextures( 1, &textureID );
+ glBindTexture( GL_TEXTURE_2D, textureID );
+
+ // Load texture from file into video memory, including mipmap levels
+ if( !glfwLoadTexture2D( texturePath, GLFW_BUILD_MIPMAPS_BIT ) )
+ {
+ fprintf( stderr, "Failed to load texture %s\n", texturePath );
+ glfwTerminate();
+ exit( EXIT_FAILURE );
+ }
+
+ // Use trilinear interpolation (GL_LINEAR_MIPMAP_LINEAR)
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR_MIPMAP_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR );
+
+ // Enable plain 2D texturing
+ glEnable( GL_TEXTURE_2D );
+
+ running = GL_TRUE;
+ while( running )
+ {
+ // Get time and mouse position
+ time = glfwGetTime();
+ glfwGetMousePos( &x, NULL );
+
+ // Get window size (may be different than the requested size)
+ glfwGetWindowSize( &width, &height );
+ height = height > 0 ? height : 1;
+
+ // Set viewport
+ glViewport( 0, 0, width, height );
+
+ // Clear color buffer
+ glClearColor( 0.0f, 0.0f, 0.0f, 0.0f);
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Select and setup the projection matrix
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ gluPerspective( 65.0f, (GLfloat)width / (GLfloat)height, 1.0f,
+ 50.0f );
+
+ // Select and setup the modelview matrix
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ gluLookAt( 0.0f, 3.0f, -20.0f, // Eye-position
+ 0.0f, -4.0f, -11.0f, // View-point
+ 0.0f, 1.0f, 0.0f ); // Up-vector
+
+ // Draw a textured quad
+ glRotatef( 0.05f * (GLfloat)x + (GLfloat)time * 5.0f, 0.0f, 1.0f, 0.0f );
+ glBegin( GL_QUADS );
+ glTexCoord2f( -20.0f, 20.0f );
+ glVertex3f( -50.0f, 0.0f, -50.0f );
+ glTexCoord2f( 20.0f, 20.0f );
+ glVertex3f( 50.0f, 0.0f, -50.0f );
+ glTexCoord2f( 20.0f, -20.0f );
+ glVertex3f( 50.0f, 0.0f, 50.0f );
+ glTexCoord2f( -20.0f, -20.0f );
+ glVertex3f( -50.0f, 0.0f, 50.0f );
+ glEnd();
+
+ // Swap buffers
+ glfwSwapBuffers();
+
+ // Check if the ESC key was pressed or the window was closed
+ running = !glfwGetKey( GLFW_KEY_ESC ) &&
+ glfwGetWindowParam( GLFW_OPENED );
+ }
+
+ // Close OpenGL window and terminate GLFW
+ glfwTerminate();
+
+ exit( EXIT_SUCCESS );
+}
+
diff --git a/examples/mipmaps.tga b/examples/mipmaps.tga
new file mode 100644
index 00000000..55f913b0
Binary files /dev/null and b/examples/mipmaps.tga differ
diff --git a/examples/particles.c b/examples/particles.c
new file mode 100644
index 00000000..403a9997
--- /dev/null
+++ b/examples/particles.c
@@ -0,0 +1,1152 @@
+//========================================================================
+// This is a simple, but cool particle engine (buzz-word meaning many
+// small objects that are treated as points and drawn as textures
+// projected on simple geometry).
+//
+// This demonstration generates a colorful fountain-like animation. It
+// uses several advanced OpenGL teqhniques:
+//
+// 1) Lighting (per vertex)
+// 2) Alpha blending
+// 3) Fog
+// 4) Texturing
+// 5) Display lists (for drawing the static environment geometry)
+// 6) Vertex arrays (for drawing the particles)
+// 7) GL_EXT_separate_specular_color is used (if available)
+//
+// Even more so, this program uses multi threading. The program is
+// essentialy divided into a main rendering thread and a particle physics
+// calculation thread. My benchmarks under Windows 2000 on a single
+// processor system show that running this program as two threads instead
+// of a single thread means no difference (there may be a very marginal
+// advantage for the multi threaded case). On dual processor systems I
+// have had reports of 5-25% of speed increase when running this program
+// as two threads instead of one thread.
+//
+// The default behaviour of this program is to use two threads. To force
+// a single thread to be used, use the command line switch -s.
+//
+// To run a fixed length benchmark (60 s), use the command line switch -b.
+//
+// Benchmark results (640x480x16, best of three tests):
+//
+// CPU GFX 1 thread 2 threads
+// Athlon XP 2700+ GeForce Ti4200 (oc) 757 FPS 759 FPS
+// P4 2.8 GHz (SMT) GeForce FX5600 548 FPS 550 FPS
+//
+// One more thing: Press 'w' during the demo to toggle wireframe mode.
+//========================================================================
+
+#include
+#include
+#include
+#include
+#include
+
+// Define tokens for GL_EXT_separate_specular_color if not already defined
+#ifndef GL_EXT_separate_specular_color
+#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8
+#define GL_SINGLE_COLOR_EXT 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA
+#endif // GL_EXT_separate_specular_color
+
+// Some 's do not define M_PI
+#ifndef M_PI
+#define M_PI 3.141592654
+#endif
+
+// Desired fullscreen resolution
+#define WIDTH 640
+#define HEIGHT 480
+
+
+//========================================================================
+// Type definitions
+//========================================================================
+
+typedef struct { float x,y,z; } VEC;
+
+// This structure is used for interleaved vertex arrays (see the
+// DrawParticles function) - Note: This structure SHOULD be packed on most
+// systems. It uses 32-bit fields on 32-bit boundaries, and is a multiple
+// of 64 bits in total (6x32=3x64). If it does not work, try using pragmas
+// or whatever to force the structure to be packed.
+typedef struct {
+ GLfloat s, t; // Texture coordinates
+ GLuint rgba; // Color (four ubytes packed into an uint)
+ GLfloat x, y, z; // Vertex coordinates
+} VERTEX;
+
+
+//========================================================================
+// Program control global variables
+//========================================================================
+
+// "Running" flag (true if program shall continue to run)
+int running;
+
+// Window dimensions
+int width, height;
+
+// "wireframe" flag (true if we use wireframe view)
+int wireframe;
+
+// "multithreading" flag (true if we use multithreading)
+int multithreading;
+
+// Thread synchronization
+struct {
+ double t; // Time (s)
+ float dt; // Time since last frame (s)
+ int p_frame; // Particle physics frame number
+ int d_frame; // Particle draw frame number
+ GLFWcond p_done; // Condition: particle physics done
+ GLFWcond d_done; // Condition: particle draw done
+ GLFWmutex particles_lock; // Particles data sharing mutex
+} thread_sync;
+
+
+//========================================================================
+// Texture declarations (we hard-code them into the source code, since
+// they are so simple)
+//========================================================================
+
+#define P_TEX_WIDTH 8 // Particle texture dimensions
+#define P_TEX_HEIGHT 8
+#define F_TEX_WIDTH 16 // Floor texture dimensions
+#define F_TEX_HEIGHT 16
+
+// Texture object IDs
+GLuint particle_tex_id, floor_tex_id;
+
+// Particle texture (a simple spot)
+const unsigned char particle_texture[ P_TEX_WIDTH * P_TEX_HEIGHT ] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x11, 0x22, 0x22, 0x11, 0x00, 0x00,
+ 0x00, 0x11, 0x33, 0x88, 0x77, 0x33, 0x11, 0x00,
+ 0x00, 0x22, 0x88, 0xff, 0xee, 0x77, 0x22, 0x00,
+ 0x00, 0x22, 0x77, 0xee, 0xff, 0x88, 0x22, 0x00,
+ 0x00, 0x11, 0x33, 0x77, 0x88, 0x33, 0x11, 0x00,
+ 0x00, 0x00, 0x11, 0x33, 0x22, 0x11, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+// Floor texture (your basic checkered floor)
+const unsigned char floor_texture[ F_TEX_WIDTH * F_TEX_HEIGHT ] = {
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0xff, 0xf0, 0xcc, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0xf0, 0xcc, 0xee, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0x30, 0x66, 0x30, 0x30, 0x30, 0x20, 0x30, 0x30,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xee, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xcc, 0xf0, 0xf0, 0xf0, 0x30, 0x30, 0x55, 0x30, 0x30, 0x44, 0x30, 0x30,
+ 0xf0, 0xdd, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0x30,
+ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x33, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x30, 0x30, 0xf0, 0xff, 0xf0, 0xf0, 0xdd, 0xf0, 0xf0, 0xff,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x55, 0x33, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0,
+ 0x30, 0x44, 0x66, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xaa, 0xf0, 0xf0, 0xcc, 0xf0,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xdd, 0xf0,
+ 0x30, 0x30, 0x30, 0x77, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+};
+
+
+//========================================================================
+// These are fixed constants that control the particle engine. In a
+// modular world, these values should be variables...
+//========================================================================
+
+// Maximum number of particles
+#define MAX_PARTICLES 3000
+
+// Life span of a particle (in seconds)
+#define LIFE_SPAN 8.0f
+
+// A new particle is born every [BIRTH_INTERVAL] second
+#define BIRTH_INTERVAL (LIFE_SPAN/(float)MAX_PARTICLES)
+
+// Particle size (meters)
+#define PARTICLE_SIZE 0.7f
+
+// Gravitational constant (m/s^2)
+#define GRAVITY 9.8f
+
+// Base initial velocity (m/s)
+#define VELOCITY 8.0f
+
+// Bounce friction (1.0 = no friction, 0.0 = maximum friction)
+#define FRICTION 0.75f
+
+// "Fountain" height (m)
+#define FOUNTAIN_HEIGHT 3.0f
+
+// Fountain radius (m)
+#define FOUNTAIN_RADIUS 1.6f
+
+// Minimum delta-time for particle phisics (s)
+#define MIN_DELTA_T (BIRTH_INTERVAL * 0.5f)
+
+
+//========================================================================
+// Particle system global variables
+//========================================================================
+
+// This structure holds all state for a single particle
+typedef struct {
+ float x,y,z; // Position in space
+ float vx,vy,vz; // Velocity vector
+ float r,g,b; // Color of particle
+ float life; // Life of particle (1.0 = newborn, < 0.0 = dead)
+ int active; // Tells if this particle is active
+} PARTICLE;
+
+// Global vectors holding all particles. We use two vectors for double
+// buffering.
+static PARTICLE particles[ MAX_PARTICLES ];
+
+// Global variable holding the age of the youngest particle
+static float min_age;
+
+// Color of latest born particle (used for fountain lighting)
+static float glow_color[4];
+
+// Position of latest born particle (used for fountain lighting)
+static float glow_pos[4];
+
+
+//========================================================================
+// Object material and fog configuration constants
+//========================================================================
+
+const GLfloat fountain_diffuse[4] = {0.7f,1.0f,1.0f,1.0f};
+const GLfloat fountain_specular[4] = {1.0f,1.0f,1.0f,1.0f};
+const GLfloat fountain_shininess = 12.0f;
+const GLfloat floor_diffuse[4] = {1.0f,0.6f,0.6f,1.0f};
+const GLfloat floor_specular[4] = {0.6f,0.6f,0.6f,1.0f};
+const GLfloat floor_shininess = 18.0f;
+const GLfloat fog_color[4] = {0.1f, 0.1f, 0.1f, 1.0f};
+
+
+//========================================================================
+// InitParticle() - Initialize a new particle
+//========================================================================
+
+void InitParticle( PARTICLE *p, double t )
+{
+ float xy_angle, velocity;
+
+ // Start position of particle is at the fountain blow-out
+ p->x = 0.0f;
+ p->y = 0.0f;
+ p->z = FOUNTAIN_HEIGHT;
+
+ // Start velocity is up (Z)...
+ p->vz = 0.7f + (0.3f/4096.f) * (float) (rand() & 4095);
+
+ // ...and a randomly chosen X/Y direction
+ xy_angle = (2.f * (float)M_PI / 4096.f) * (float) (rand() & 4095);
+ p->vx = 0.4f * (float) cos( xy_angle );
+ p->vy = 0.4f * (float) sin( xy_angle );
+
+ // Scale velocity vector according to a time-varying velocity
+ velocity = VELOCITY*(0.8f + 0.1f*(float)(sin( 0.5*t )+sin( 1.31*t )));
+ p->vx *= velocity;
+ p->vy *= velocity;
+ p->vz *= velocity;
+
+ // Color is time-varying
+ p->r = 0.7f + 0.3f * (float) sin( 0.34*t + 0.1 );
+ p->g = 0.6f + 0.4f * (float) sin( 0.63*t + 1.1 );
+ p->b = 0.6f + 0.4f * (float) sin( 0.91*t + 2.1 );
+
+ // Store settings for fountain glow lighting
+ glow_pos[0] = 0.4f * (float) sin( 1.34*t );
+ glow_pos[1] = 0.4f * (float) sin( 3.11*t );
+ glow_pos[2] = FOUNTAIN_HEIGHT + 1.0f;
+ glow_pos[3] = 1.0f;
+ glow_color[0] = p->r;
+ glow_color[1] = p->g;
+ glow_color[2] = p->b;
+ glow_color[3] = 1.0f;
+
+ // The particle is new-born and active
+ p->life = 1.0f;
+ p->active = 1;
+}
+
+
+//========================================================================
+// UpdateParticle() - Update a particle
+//========================================================================
+
+#define FOUNTAIN_R2 (FOUNTAIN_RADIUS+PARTICLE_SIZE/2)*(FOUNTAIN_RADIUS+PARTICLE_SIZE/2)
+
+void UpdateParticle( PARTICLE *p, float dt )
+{
+ // If the particle is not active, we need not do anything
+ if( !p->active )
+ {
+ return;
+ }
+
+ // The particle is getting older...
+ p->life = p->life - dt * (1.0f / LIFE_SPAN);
+
+ // Did the particle die?
+ if( p->life <= 0.0f )
+ {
+ p->active = 0;
+ return;
+ }
+
+ // Update particle velocity (apply gravity)
+ p->vz = p->vz - GRAVITY * dt;
+
+ // Update particle position
+ p->x = p->x + p->vx * dt;
+ p->y = p->y + p->vy * dt;
+ p->z = p->z + p->vz * dt;
+
+ // Simple collision detection + response
+ if( p->vz < 0.0f )
+ {
+ // Particles should bounce on the fountain (with friction)
+ if( (p->x*p->x + p->y*p->y) < FOUNTAIN_R2 &&
+ p->z < (FOUNTAIN_HEIGHT + PARTICLE_SIZE/2) )
+ {
+ p->vz = -FRICTION * p->vz;
+ p->z = FOUNTAIN_HEIGHT + PARTICLE_SIZE/2 +
+ FRICTION * (FOUNTAIN_HEIGHT +
+ PARTICLE_SIZE/2 - p->z);
+ }
+
+ // Particles should bounce on the floor (with friction)
+ else if( p->z < PARTICLE_SIZE/2 )
+ {
+ p->vz = -FRICTION * p->vz;
+ p->z = PARTICLE_SIZE/2 +
+ FRICTION * (PARTICLE_SIZE/2 - p->z);
+ }
+
+ }
+}
+
+
+//========================================================================
+// ParticleEngine() - The main frame for the particle engine. Called once
+// per frame.
+//========================================================================
+
+void ParticleEngine( double t, float dt )
+{
+ int i;
+ float dt2;
+
+ // Update particles (iterated several times per frame if dt is too
+ // large)
+ while( dt > 0.0f )
+ {
+ // Calculate delta time for this iteration
+ dt2 = dt < MIN_DELTA_T ? dt : MIN_DELTA_T;
+
+ // Update particles
+ for( i = 0; i < MAX_PARTICLES; i ++ )
+ {
+ UpdateParticle( &particles[ i ], dt2 );
+ }
+
+ // Increase minimum age
+ min_age += dt2;
+
+ // Should we create any new particle(s)?
+ while( min_age >= BIRTH_INTERVAL )
+ {
+ min_age -= BIRTH_INTERVAL;
+
+ // Find a dead particle to replace with a new one
+ for( i = 0; i < MAX_PARTICLES; i ++ )
+ {
+ if( !particles[ i ].active )
+ {
+ InitParticle( &particles[ i ], t + min_age );
+ UpdateParticle( &particles[ i ], min_age );
+ break;
+ }
+ }
+ }
+
+ // Decrease frame delta time
+ dt -= dt2;
+ }
+}
+
+
+//========================================================================
+// DrawParticles() - Draw all active particles. We use OpenGL 1.1 vertex
+// arrays for this in order to accelerate the drawing.
+//========================================================================
+
+#define BATCH_PARTICLES 70 // Number of particles to draw in each batch
+ // (70 corresponds to 7.5 KB = will not blow
+ // the L1 data cache on most CPUs)
+#define PARTICLE_VERTS 4 // Number of vertices per particle
+
+void DrawParticles( double t, float dt )
+{
+ int i, particle_count;
+ VERTEX vertex_array[ BATCH_PARTICLES * PARTICLE_VERTS ], *vptr;
+ float alpha;
+ GLuint rgba;
+ VEC quad_lower_left, quad_lower_right;
+ GLfloat mat[ 16 ];
+ PARTICLE *pptr;
+
+ // Here comes the real trick with flat single primitive objects (s.c.
+ // "billboards"): We must rotate the textured primitive so that it
+ // always faces the viewer (is coplanar with the view-plane).
+ // We:
+ // 1) Create the primitive around origo (0,0,0)
+ // 2) Rotate it so that it is coplanar with the view plane
+ // 3) Translate it according to the particle position
+ // Note that 1) and 2) is the same for all particles (done only once).
+
+ // Get modelview matrix. We will only use the upper left 3x3 part of
+ // the matrix, which represents the rotation.
+ glGetFloatv( GL_MODELVIEW_MATRIX, mat );
+
+ // 1) & 2) We do it in one swift step:
+ // Although not obvious, the following six lines represent two matrix/
+ // vector multiplications. The matrix is the inverse 3x3 rotation
+ // matrix (i.e. the transpose of the same matrix), and the two vectors
+ // represent the lower left corner of the quad, PARTICLE_SIZE/2 *
+ // (-1,-1,0), and the lower right corner, PARTICLE_SIZE/2 * (1,-1,0).
+ // The upper left/right corners of the quad is always the negative of
+ // the opposite corners (regardless of rotation).
+ quad_lower_left.x = (-PARTICLE_SIZE/2) * (mat[0] + mat[1]);
+ quad_lower_left.y = (-PARTICLE_SIZE/2) * (mat[4] + mat[5]);
+ quad_lower_left.z = (-PARTICLE_SIZE/2) * (mat[8] + mat[9]);
+ quad_lower_right.x = (PARTICLE_SIZE/2) * (mat[0] - mat[1]);
+ quad_lower_right.y = (PARTICLE_SIZE/2) * (mat[4] - mat[5]);
+ quad_lower_right.z = (PARTICLE_SIZE/2) * (mat[8] - mat[9]);
+
+ // Don't update z-buffer, since all particles are transparent!
+ glDepthMask( GL_FALSE );
+
+ // Enable blending
+ glEnable( GL_BLEND );
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE );
+
+ // Select particle texture
+ if( !wireframe )
+ {
+ glEnable( GL_TEXTURE_2D );
+ glBindTexture( GL_TEXTURE_2D, particle_tex_id );
+ }
+
+ // Set up vertex arrays. We use interleaved arrays, which is easier to
+ // handle (in most situations) and it gives a linear memeory access
+ // access pattern (which may give better performance in some
+ // situations). GL_T2F_C4UB_V3F means: 2 floats for texture coords,
+ // 4 ubytes for color and 3 floats for vertex coord (in that order).
+ // Most OpenGL cards / drivers are optimized for this format.
+ glInterleavedArrays( GL_T2F_C4UB_V3F, 0, vertex_array );
+
+ // Is particle physics carried out in a separate thread?
+ if( multithreading )
+ {
+ // Wait for particle physics thread to be done
+ glfwLockMutex( thread_sync.particles_lock );
+ while( running && thread_sync.p_frame <= thread_sync.d_frame )
+ {
+ glfwWaitCond( thread_sync.p_done, thread_sync.particles_lock,
+ 0.1 );
+ }
+
+ // Store the frame time and delta time for the physics thread
+ thread_sync.t = t;
+ thread_sync.dt = dt;
+
+ // Update frame counter
+ thread_sync.d_frame ++;
+ }
+ else
+ {
+ // Perform particle physics in this thread
+ ParticleEngine( t, dt );
+ }
+
+ // Loop through all particles and build vertex arrays.
+ particle_count = 0;
+ vptr = vertex_array;
+ pptr = particles;
+ for( i = 0; i < MAX_PARTICLES; i ++ )
+ {
+ if( pptr->active )
+ {
+ // Calculate particle intensity (we set it to max during 75%
+ // of its life, then it fades out)
+ alpha = 4.0f * pptr->life;
+ if( alpha > 1.0f )
+ {
+ alpha = 1.0f;
+ }
+
+ // Convert color from float to 8-bit (store it in a 32-bit
+ // integer using endian independent type casting)
+ ((GLubyte *)&rgba)[0] = (GLubyte)(pptr->r * 255.0f);
+ ((GLubyte *)&rgba)[1] = (GLubyte)(pptr->g * 255.0f);
+ ((GLubyte *)&rgba)[2] = (GLubyte)(pptr->b * 255.0f);
+ ((GLubyte *)&rgba)[3] = (GLubyte)(alpha * 255.0f);
+
+ // 3) Translate the quad to the correct position in modelview
+ // space and store its parameters in vertex arrays (we also
+ // store texture coord and color information for each vertex).
+
+ // Lower left corner
+ vptr->s = 0.0f;
+ vptr->t = 0.0f;
+ vptr->rgba = rgba;
+ vptr->x = pptr->x + quad_lower_left.x;
+ vptr->y = pptr->y + quad_lower_left.y;
+ vptr->z = pptr->z + quad_lower_left.z;
+ vptr ++;
+
+ // Lower right corner
+ vptr->s = 1.0f;
+ vptr->t = 0.0f;
+ vptr->rgba = rgba;
+ vptr->x = pptr->x + quad_lower_right.x;
+ vptr->y = pptr->y + quad_lower_right.y;
+ vptr->z = pptr->z + quad_lower_right.z;
+ vptr ++;
+
+ // Upper right corner
+ vptr->s = 1.0f;
+ vptr->t = 1.0f;
+ vptr->rgba = rgba;
+ vptr->x = pptr->x - quad_lower_left.x;
+ vptr->y = pptr->y - quad_lower_left.y;
+ vptr->z = pptr->z - quad_lower_left.z;
+ vptr ++;
+
+ // Upper left corner
+ vptr->s = 0.0f;
+ vptr->t = 1.0f;
+ vptr->rgba = rgba;
+ vptr->x = pptr->x - quad_lower_right.x;
+ vptr->y = pptr->y - quad_lower_right.y;
+ vptr->z = pptr->z - quad_lower_right.z;
+ vptr ++;
+
+ // Increase count of drawable particles
+ particle_count ++;
+ }
+
+ // If we have filled up one batch of particles, draw it as a set
+ // of quads using glDrawArrays.
+ if( particle_count >= BATCH_PARTICLES )
+ {
+ // The first argument tells which primitive type we use (QUAD)
+ // The second argument tells the index of the first vertex (0)
+ // The last argument is the vertex count
+ glDrawArrays( GL_QUADS, 0, PARTICLE_VERTS * particle_count );
+ particle_count = 0;
+ vptr = vertex_array;
+ }
+
+ // Next particle
+ pptr ++;
+ }
+
+ // We are done with the particle data: Unlock mutex and signal physics
+ // thread
+ if( multithreading )
+ {
+ glfwUnlockMutex( thread_sync.particles_lock );
+ glfwSignalCond( thread_sync.d_done );
+ }
+
+ // Draw final batch of particles (if any)
+ glDrawArrays( GL_QUADS, 0, PARTICLE_VERTS * particle_count );
+
+ // Disable vertex arrays (Note: glInterleavedArrays implicitly called
+ // glEnableClientState for vertex, texture coord and color arrays)
+ glDisableClientState( GL_VERTEX_ARRAY );
+ glDisableClientState( GL_TEXTURE_COORD_ARRAY );
+ glDisableClientState( GL_COLOR_ARRAY );
+
+ // Disable texturing and blending
+ glDisable( GL_TEXTURE_2D );
+ glDisable( GL_BLEND );
+
+ // Allow Z-buffer updates again
+ glDepthMask( GL_TRUE );
+}
+
+
+//========================================================================
+// Fountain geometry specification
+//========================================================================
+
+#define FOUNTAIN_SIDE_POINTS 14
+#define FOUNTAIN_SWEEP_STEPS 32
+
+static const float fountain_side[ FOUNTAIN_SIDE_POINTS*2 ] = {
+ 1.2f, 0.0f, 1.0f, 0.2f, 0.41f, 0.3f, 0.4f, 0.35f,
+ 0.4f, 1.95f, 0.41f, 2.0f, 0.8f, 2.2f, 1.2f, 2.4f,
+ 1.5f, 2.7f, 1.55f,2.95f, 1.6f, 3.0f, 1.0f, 3.0f,
+ 0.5f, 3.0f, 0.0f, 3.0f
+};
+
+static const float fountain_normal[ FOUNTAIN_SIDE_POINTS*2 ] = {
+ 1.0000f, 0.0000f, 0.6428f, 0.7660f, 0.3420f, 0.9397f, 1.0000f, 0.0000f,
+ 1.0000f, 0.0000f, 0.3420f,-0.9397f, 0.4226f,-0.9063f, 0.5000f,-0.8660f,
+ 0.7660f,-0.6428f, 0.9063f,-0.4226f, 0.0000f,1.00000f, 0.0000f,1.00000f,
+ 0.0000f,1.00000f, 0.0000f,1.00000f
+};
+
+
+//========================================================================
+// DrawFountain() - Draw a fountain
+//========================================================================
+
+void DrawFountain( void )
+{
+ static GLuint fountain_list = 0;
+ double angle;
+ float x, y;
+ int m, n;
+
+ // The first time, we build the fountain display list
+ if( !fountain_list )
+ {
+ // Start recording of a new display list
+ fountain_list = glGenLists( 1 );
+ glNewList( fountain_list, GL_COMPILE_AND_EXECUTE );
+
+ // Set fountain material
+ glMaterialfv( GL_FRONT, GL_DIFFUSE, fountain_diffuse );
+ glMaterialfv( GL_FRONT, GL_SPECULAR, fountain_specular );
+ glMaterialf( GL_FRONT, GL_SHININESS, fountain_shininess );
+
+ // Build fountain using triangle strips
+ for( n = 0; n < FOUNTAIN_SIDE_POINTS-1; n ++ )
+ {
+ glBegin( GL_TRIANGLE_STRIP );
+ for( m = 0; m <= FOUNTAIN_SWEEP_STEPS; m ++ )
+ {
+ angle = (double) m * (2.0*M_PI/(double)FOUNTAIN_SWEEP_STEPS);
+ x = (float) cos( angle );
+ y = (float) sin( angle );
+
+ // Draw triangle strip
+ glNormal3f( x * fountain_normal[ n*2+2 ],
+ y * fountain_normal[ n*2+2 ],
+ fountain_normal[ n*2+3 ] );
+ glVertex3f( x * fountain_side[ n*2+2 ],
+ y * fountain_side[ n*2+2 ],
+ fountain_side[ n*2+3 ] );
+ glNormal3f( x * fountain_normal[ n*2 ],
+ y * fountain_normal[ n*2 ],
+ fountain_normal[ n*2+1 ] );
+ glVertex3f( x * fountain_side[ n*2 ],
+ y * fountain_side[ n*2 ],
+ fountain_side[ n*2+1 ] );
+ }
+ glEnd();
+ }
+
+ // End recording of display list
+ glEndList();
+ }
+ else
+ {
+ // Playback display list
+ glCallList( fountain_list );
+ }
+}
+
+
+//========================================================================
+// TesselateFloor() - Recursive function for building variable tesselated
+// floor
+//========================================================================
+
+void TesselateFloor( float x1, float y1, float x2, float y2,
+ int recursion )
+{
+ float delta, x, y;
+
+ // Last recursion?
+ if( recursion >= 5 )
+ {
+ delta = 999999.0f;
+ }
+ else
+ {
+ x = (float) (fabs(x1) < fabs(x2) ? fabs(x1) : fabs(x2));
+ y = (float) (fabs(y1) < fabs(y2) ? fabs(y1) : fabs(y2));
+ delta = x*x + y*y;
+ }
+
+ // Recurse further?
+ if( delta < 0.1f )
+ {
+ x = (x1+x2) * 0.5f;
+ y = (y1+y2) * 0.5f;
+ TesselateFloor( x1,y1, x, y, recursion + 1 );
+ TesselateFloor( x,y1, x2, y, recursion + 1 );
+ TesselateFloor( x1, y, x,y2, recursion + 1 );
+ TesselateFloor( x, y, x2,y2, recursion + 1 );
+ }
+ else
+ {
+ glTexCoord2f( x1*30.0f, y1*30.0f );
+ glVertex3f( x1*80.0f, y1*80.0f , 0.0f );
+ glTexCoord2f( x2*30.0f, y1*30.0f );
+ glVertex3f( x2*80.0f, y1*80.0f , 0.0f );
+ glTexCoord2f( x2*30.0f, y2*30.0f );
+ glVertex3f( x2*80.0f, y2*80.0f , 0.0f );
+ glTexCoord2f( x1*30.0f, y2*30.0f );
+ glVertex3f( x1*80.0f, y2*80.0f , 0.0f );
+ }
+}
+
+
+//========================================================================
+// DrawFloor() - Draw floor. We builde the floor recursively, and let the
+// tesselation in the centre (near x,y=0,0) be high, while the selleation
+// around the edges be low.
+//========================================================================
+
+void DrawFloor( void )
+{
+ static GLuint floor_list = 0;
+
+ // Select floor texture
+ if( !wireframe )
+ {
+ glEnable( GL_TEXTURE_2D );
+ glBindTexture( GL_TEXTURE_2D, floor_tex_id );
+ }
+
+ // The first time, we build the floor display list
+ if( !floor_list )
+ {
+ // Start recording of a new display list
+ floor_list = glGenLists( 1 );
+ glNewList( floor_list, GL_COMPILE_AND_EXECUTE );
+
+ // Set floor material
+ glMaterialfv( GL_FRONT, GL_DIFFUSE, floor_diffuse );
+ glMaterialfv( GL_FRONT, GL_SPECULAR, floor_specular );
+ glMaterialf( GL_FRONT, GL_SHININESS, floor_shininess );
+
+ // Draw floor as a bunch of triangle strips (high tesselation
+ // improves lighting)
+ glNormal3f( 0.0f, 0.0f, 1.0f );
+ glBegin( GL_QUADS );
+ TesselateFloor( -1.0f,-1.0f, 0.0f,0.0f, 0 );
+ TesselateFloor( 0.0f,-1.0f, 1.0f,0.0f, 0 );
+ TesselateFloor( 0.0f, 0.0f, 1.0f,1.0f, 0 );
+ TesselateFloor( -1.0f, 0.0f, 0.0f,1.0f, 0 );
+ glEnd();
+
+ // End recording of display list
+ glEndList();
+ }
+ else
+ {
+ // Playback display list
+ glCallList( floor_list );
+ }
+
+ glDisable( GL_TEXTURE_2D );
+
+}
+
+
+//========================================================================
+// SetupLights() - Position and configure light sources
+//========================================================================
+
+void SetupLights( void )
+{
+ float l1pos[4], l1amb[4], l1dif[4], l1spec[4];
+ float l2pos[4], l2amb[4], l2dif[4], l2spec[4];
+
+ // Set light source 1 parameters
+ l1pos[0] = 0.0f; l1pos[1] = -9.0f; l1pos[2] = 8.0f; l1pos[3] = 1.0f;
+ l1amb[0] = 0.2f; l1amb[1] = 0.2f; l1amb[2] = 0.2f; l1amb[3] = 1.0f;
+ l1dif[0] = 0.8f; l1dif[1] = 0.4f; l1dif[2] = 0.2f; l1dif[3] = 1.0f;
+ l1spec[0] = 1.0f; l1spec[1] = 0.6f; l1spec[2] = 0.2f; l1spec[3] = 0.0f;
+
+ // Set light source 2 parameters
+ l2pos[0] = -15.0f; l2pos[1] = 12.0f; l2pos[2] = 1.5f; l2pos[3] = 1.0f;
+ l2amb[0] = 0.0f; l2amb[1] = 0.0f; l2amb[2] = 0.0f; l2amb[3] = 1.0f;
+ l2dif[0] = 0.2f; l2dif[1] = 0.4f; l2dif[2] = 0.8f; l2dif[3] = 1.0f;
+ l2spec[0] = 0.2f; l2spec[1] = 0.6f; l2spec[2] = 1.0f; l2spec[3] = 0.0f;
+
+ // Configure light sources in OpenGL
+ glLightfv( GL_LIGHT1, GL_POSITION, l1pos );
+ glLightfv( GL_LIGHT1, GL_AMBIENT, l1amb );
+ glLightfv( GL_LIGHT1, GL_DIFFUSE, l1dif );
+ glLightfv( GL_LIGHT1, GL_SPECULAR, l1spec );
+ glLightfv( GL_LIGHT2, GL_POSITION, l2pos );
+ glLightfv( GL_LIGHT2, GL_AMBIENT, l2amb );
+ glLightfv( GL_LIGHT2, GL_DIFFUSE, l2dif );
+ glLightfv( GL_LIGHT2, GL_SPECULAR, l2spec );
+ glLightfv( GL_LIGHT3, GL_POSITION, glow_pos );
+ glLightfv( GL_LIGHT3, GL_DIFFUSE, glow_color );
+ glLightfv( GL_LIGHT3, GL_SPECULAR, glow_color );
+
+ // Enable light sources
+ glEnable( GL_LIGHT1 );
+ glEnable( GL_LIGHT2 );
+ glEnable( GL_LIGHT3 );
+}
+
+
+//========================================================================
+// Draw() - Main rendering function
+//========================================================================
+
+void Draw( double t )
+{
+ double xpos, ypos, zpos, angle_x, angle_y, angle_z;
+ static double t_old = 0.0;
+ float dt;
+
+ // Calculate frame-to-frame delta time
+ dt = (float)(t-t_old);
+ t_old = t;
+
+ // Setup viewport
+ glViewport( 0, 0, width, height );
+
+ // Clear color and Z-buffer
+ glClearColor( 0.1f, 0.1f, 0.1f, 1.0f );
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+ // Setup projection
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ gluPerspective( 65.0, (double)width/(double)height, 1.0, 60.0 );
+
+ // Setup camera
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Rotate camera
+ angle_x = 90.0 - 10.0;
+ angle_y = 10.0 * sin( 0.3 * t );
+ angle_z = 10.0 * t;
+ glRotated( -angle_x, 1.0, 0.0, 0.0 );
+ glRotated( -angle_y, 0.0, 1.0, 0.0 );
+ glRotated( -angle_z, 0.0, 0.0, 1.0 );
+
+ // Translate camera
+ xpos = 15.0 * sin( (M_PI/180.0) * angle_z ) +
+ 2.0 * sin( (M_PI/180.0) * 3.1 * t );
+ ypos = -15.0 * cos( (M_PI/180.0) * angle_z ) +
+ 2.0 * cos( (M_PI/180.0) * 2.9 * t );
+ zpos = 4.0 + 2.0 * cos( (M_PI/180.0) * 4.9 * t );
+ glTranslated( -xpos, -ypos, -zpos );
+
+ // Enable face culling
+ glFrontFace( GL_CCW );
+ glCullFace( GL_BACK );
+ glEnable( GL_CULL_FACE );
+
+ // Enable lighting
+ SetupLights();
+ glEnable( GL_LIGHTING );
+
+ // Enable fog (dim details far away)
+ glEnable( GL_FOG );
+ glFogi( GL_FOG_MODE, GL_EXP );
+ glFogf( GL_FOG_DENSITY, 0.05f );
+ glFogfv( GL_FOG_COLOR, fog_color );
+
+ // Draw floor
+ DrawFloor();
+
+ // Enable Z-buffering
+ glEnable( GL_DEPTH_TEST );
+ glDepthFunc( GL_LEQUAL );
+ glDepthMask( GL_TRUE );
+
+ // Draw fountain
+ DrawFountain();
+
+ // Disable fog & lighting
+ glDisable( GL_LIGHTING );
+ glDisable( GL_FOG );
+
+ // Draw all particles (must be drawn after all solid objects have been
+ // drawn!)
+ DrawParticles( t, dt );
+
+ // Z-buffer not needed anymore
+ glDisable( GL_DEPTH_TEST );
+}
+
+
+//========================================================================
+// Resize() - GLFW window resize callback function
+//========================================================================
+
+void GLFWCALL Resize( int x, int y )
+{
+ width = x;
+ height = y > 0 ? y : 1; // Prevent division by zero in aspect calc.
+}
+
+
+//========================================================================
+// Input callback functions
+//========================================================================
+
+void GLFWCALL KeyFun( int key, int action )
+{
+ if( action == GLFW_PRESS )
+ {
+ switch( key )
+ {
+ case GLFW_KEY_ESC:
+ running = 0;
+ break;
+ case 'W':
+ wireframe = !wireframe;
+ glPolygonMode( GL_FRONT_AND_BACK,
+ wireframe ? GL_LINE : GL_FILL );
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+
+//========================================================================
+// PhysicsThreadFun() - Thread for updating particle physics
+//========================================================================
+
+void GLFWCALL PhysicsThreadFun( void *arg )
+{
+ while( running )
+ {
+ // Lock mutex
+ glfwLockMutex( thread_sync.particles_lock );
+
+ // Wait for particle drawing to be done
+ while( running && thread_sync.p_frame > thread_sync.d_frame )
+ {
+ glfwWaitCond( thread_sync.d_done, thread_sync.particles_lock,
+ 0.1 );
+ }
+
+ // No longer running?
+ if( !running )
+ {
+ break;
+ }
+
+ // Update particles
+ ParticleEngine( thread_sync.t, thread_sync.dt );
+
+ // Update frame counter
+ thread_sync.p_frame ++;
+
+ // Unlock mutex and signal drawing thread
+ glfwUnlockMutex( thread_sync.particles_lock );
+ glfwSignalCond( thread_sync.p_done );
+ }
+}
+
+
+//========================================================================
+// main()
+//========================================================================
+
+int main( int argc, char **argv )
+{
+ int i, frames, benchmark;
+ double t0, t;
+ GLFWthread physics_thread = 0;
+
+ // Use multithreading by default, but don't benchmark
+ multithreading = 1;
+ benchmark = 0;
+
+ // Check command line arguments
+ for( i = 1; i < argc; i ++ )
+ {
+ // Use benchmarking?
+ if( strcmp( argv[i], "-b" ) == 0 )
+ {
+ benchmark = 1;
+ }
+
+ // Force multithreading off?
+ else if( strcmp( argv[i], "-s" ) == 0 )
+ {
+ multithreading = 0;
+ }
+
+ // With a Finder launch on Mac OS X we get a bogus -psn_0_46268417
+ // kind of argument (actual numbers vary). Ignore it.
+ else if( strncmp( argv[i], "-psn_", 5) == 0 );
+
+ // Usage
+ else
+ {
+ if( strcmp( argv[i], "-?" ) != 0 )
+ {
+ printf( "Unknonwn option %s\n\n", argv[ i ] );
+ }
+ printf( "Usage: %s [options]\n", argv[ 0 ] );
+ printf( "\n");
+ printf( "Options:\n" );
+ printf( " -b Benchmark (run program for 60 s)\n" );
+ printf( " -s Run program as single thread (default is to use two threads)\n" );
+ printf( " -? Display this text\n" );
+ printf( "\n");
+ printf( "Program runtime controls:\n" );
+ printf( " w Toggle wireframe mode\n" );
+ printf( " ESC Exit program\n" );
+ exit( 0 );
+ }
+ }
+
+ // Initialize GLFW
+ if( !glfwInit() )
+ {
+ fprintf( stderr, "Failed to initialize GLFW\n" );
+ exit( EXIT_FAILURE );
+ }
+
+ // Open OpenGL fullscreen window
+ if( !glfwOpenWindow( WIDTH, HEIGHT, 0,0,0,0, 16,0, GLFW_FULLSCREEN ) )
+ {
+ fprintf( stderr, "Failed to open GLFW window\n" );
+ glfwTerminate();
+ exit( EXIT_FAILURE );
+ }
+
+ // Set window title
+ glfwSetWindowTitle( "Particle engine" );
+
+ // Disable VSync (we want to get as high FPS as possible!)
+ glfwSwapInterval( 0 );
+
+ // Window resize callback function
+ glfwSetWindowSizeCallback( Resize );
+
+ // Set keyboard input callback function
+ glfwSetKeyCallback( KeyFun );
+
+ // Upload particle texture
+ glGenTextures( 1, &particle_tex_id );
+ glBindTexture( GL_TEXTURE_2D, particle_tex_id );
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, P_TEX_WIDTH, P_TEX_HEIGHT,
+ 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, particle_texture );
+
+ // Upload floor texture
+ glGenTextures( 1, &floor_tex_id );
+ glBindTexture( GL_TEXTURE_2D, floor_tex_id );
+ glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, F_TEX_WIDTH, F_TEX_HEIGHT,
+ 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, floor_texture );
+
+ // Check if we have GL_EXT_separate_specular_color, and if so use it
+ if( glfwExtensionSupported( "GL_EXT_separate_specular_color" ) )
+ {
+ glLightModeli( GL_LIGHT_MODEL_COLOR_CONTROL_EXT,
+ GL_SEPARATE_SPECULAR_COLOR_EXT );
+ }
+
+ // Set filled polygon mode as default (not wireframe)
+ glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
+ wireframe = 0;
+
+ // Clear particle system
+ for( i = 0; i < MAX_PARTICLES; i ++ )
+ {
+ particles[ i ].active = 0;
+ }
+ min_age = 0.0f;
+
+ // Set "running" flag
+ running = 1;
+
+ // Set initial times
+ thread_sync.t = 0.0;
+ thread_sync.dt = 0.001f;
+
+ // Init threading
+ if( multithreading )
+ {
+ thread_sync.p_frame = 0;
+ thread_sync.d_frame = 0;
+ thread_sync.particles_lock = glfwCreateMutex();
+ thread_sync.p_done = glfwCreateCond();
+ thread_sync.d_done = glfwCreateCond();
+ physics_thread = glfwCreateThread( PhysicsThreadFun, NULL );
+ }
+
+ // Main loop
+ t0 = glfwGetTime();
+ frames = 0;
+ while( running )
+ {
+ // Get frame time
+ t = glfwGetTime() - t0;
+
+ // Draw...
+ Draw( t );
+
+ // Swap buffers
+ glfwSwapBuffers();
+
+ // Check if window was closed
+ running = running && glfwGetWindowParam( GLFW_OPENED );
+
+ // Increase frame count
+ frames ++;
+
+ // End of benchmark?
+ if( benchmark && t >= 60.0 )
+ {
+ running = 0;
+ }
+ }
+ t = glfwGetTime() - t0;
+
+ // Wait for particle physics thread to die
+ if( multithreading )
+ {
+ glfwWaitThread( physics_thread, GLFW_WAIT );
+ }
+
+ // Display profiling information
+ printf( "%d frames in %.2f seconds = %.1f FPS", frames, t,
+ (double)frames / t );
+ printf( " (multithreading %s)\n", multithreading ? "on" : "off" );
+
+ // Terminate OpenGL
+ glfwTerminate();
+
+ exit( EXIT_SUCCESS );
+}
+
diff --git a/examples/pong3d.c b/examples/pong3d.c
new file mode 100644
index 00000000..1d1afd1f
--- /dev/null
+++ b/examples/pong3d.c
@@ -0,0 +1,854 @@
+//========================================================================
+// This is a small test application for GLFW.
+// This is an OpenGL port of the famous "PONG" game (the first computer
+// game ever?). It is very simple, and could be improved alot. It was
+// created in order to show off the gaming capabilities of GLFW.
+//========================================================================
+
+#include
+#include
+#include
+#include
+
+
+//========================================================================
+// Constants
+//========================================================================
+
+// Screen resolution
+#define WIDTH 640
+#define HEIGHT 480
+
+// Player size (units)
+#define PLAYER_XSIZE 0.05f
+#define PLAYER_YSIZE 0.15f
+
+// Ball size (units)
+#define BALL_SIZE 0.02f
+
+// Maximum player movement speed (units / second)
+#define MAX_SPEED 1.5f
+
+// Player movement acceleration (units / seconds^2)
+#define ACCELERATION 4.0f
+
+// Player movement deceleration (units / seconds^2)
+#define DECELERATION 2.0f
+
+// Ball movement speed (units / second)
+#define BALL_SPEED 0.4f
+
+// Menu options
+#define MENU_NONE 0
+#define MENU_PLAY 1
+#define MENU_QUIT 2
+
+// Game events
+#define NOBODY_WINS 0
+#define PLAYER1_WINS 1
+#define PLAYER2_WINS 2
+
+// Winner ID
+#define NOBODY 0
+#define PLAYER1 1
+#define PLAYER2 2
+
+// Camera positions
+#define CAMERA_CLASSIC 0
+#define CAMERA_ABOVE 1
+#define CAMERA_SPECTATOR 2
+#define CAMERA_DEFAULT CAMERA_CLASSIC
+
+
+//========================================================================
+// Textures
+//========================================================================
+
+#define TEX_TITLE 0
+#define TEX_MENU 1
+#define TEX_INSTR 2
+#define TEX_WINNER1 3
+#define TEX_WINNER2 4
+#define TEX_FIELD 5
+#define NUM_TEXTURES 6
+
+// Texture names
+char * tex_name[ NUM_TEXTURES ] = {
+ "pong3d_title.tga",
+ "pong3d_menu.tga",
+ "pong3d_instr.tga",
+ "pong3d_winner1.tga",
+ "pong3d_winner2.tga",
+ "pong3d_field.tga"
+};
+
+// OpenGL texture object IDs
+GLuint tex_id[ NUM_TEXTURES ];
+
+
+//========================================================================
+// Global variables
+//========================================================================
+
+// Display information
+int width, height;
+
+// Frame information
+double thistime, oldtime, dt, starttime;
+
+// Camera information
+int camerapos;
+
+// Player information
+struct {
+ double ypos; // -1.0 to +1.0
+ double yspeed; // -MAX_SPEED to +MAX_SPEED
+} player1, player2;
+
+// Ball information
+struct {
+ double xpos, ypos;
+ double xspeed, yspeed;
+} ball;
+
+// And the winner is...
+int winner;
+
+// Lighting configuration
+const GLfloat env_ambient[4] = {1.0f,1.0f,1.0f,1.0f};
+const GLfloat light1_position[4] = {-3.0f,3.0f,2.0f,1.0f};
+const GLfloat light1_diffuse[4] = {1.0f,1.0f,1.0f,0.0f};
+const GLfloat light1_ambient[4] = {0.0f,0.0f,0.0f,0.0f};
+
+// Object material properties
+const GLfloat player1_diffuse[4] = {1.0f,0.3f,0.3f,1.0f};
+const GLfloat player1_ambient[4] = {0.3f,0.1f,0.0f,1.0f};
+const GLfloat player2_diffuse[4] = {0.3f,1.0f,0.3f,1.0f};
+const GLfloat player2_ambient[4] = {0.1f,0.3f,0.1f,1.0f};
+const GLfloat ball_diffuse[4] = {1.0f,1.0f,0.5f,1.0f};
+const GLfloat ball_ambient[4] = {0.3f,0.3f,0.1f,1.0f};
+const GLfloat border_diffuse[4] = {0.3f,0.3f,1.0f,1.0f};
+const GLfloat border_ambient[4] = {0.1f,0.1f,0.3f,1.0f};
+const GLfloat floor_diffuse[4] = {1.0f,1.0f,1.0f,1.0f};
+const GLfloat floor_ambient[4] = {0.3f,0.3f,0.3f,1.0f};
+
+
+//========================================================================
+// LoadTextures() - Load textures from disk and upload to OpenGL card
+//========================================================================
+
+GLboolean LoadTextures( void )
+{
+ int i;
+
+ // Generate texture objects
+ glGenTextures( NUM_TEXTURES, tex_id );
+
+ // Load textures
+ for( i = 0; i < NUM_TEXTURES; i ++ )
+ {
+ // Select texture object
+ glBindTexture( GL_TEXTURE_2D, tex_id[ i ] );
+
+ // Set texture parameters
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+
+ // Upload texture from file to texture memory
+ if( !glfwLoadTexture2D( tex_name[ i ], 0 ) )
+ {
+ fprintf( stderr, "Failed to load texture %s\n", tex_name[ i ] );
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+//========================================================================
+// DrawImage() - Draw a 2D image as a texture
+//========================================================================
+
+void DrawImage( int texnum, float x1, float x2, float y1, float y2 )
+{
+ glEnable( GL_TEXTURE_2D );
+ glBindTexture( GL_TEXTURE_2D, tex_id[ texnum ] );
+ glBegin( GL_QUADS );
+ glTexCoord2f( 0.0f, 1.0f );
+ glVertex2f( x1, y1 );
+ glTexCoord2f( 1.0f, 1.0f );
+ glVertex2f( x2, y1 );
+ glTexCoord2f( 1.0f, 0.0f );
+ glVertex2f( x2, y2 );
+ glTexCoord2f( 0.0f, 0.0f );
+ glVertex2f( x1, y2 );
+ glEnd();
+ glDisable( GL_TEXTURE_2D );
+}
+
+
+//========================================================================
+// GameMenu() - Game menu (returns menu option)
+//========================================================================
+
+int GameMenu( void )
+{
+ int option;
+
+ // Enable sticky keys
+ glfwEnable( GLFW_STICKY_KEYS );
+
+ // Wait for a game menu key to be pressed
+ do
+ {
+ // Get window size
+ glfwGetWindowSize( &width, &height );
+
+ // Set viewport
+ glViewport( 0, 0, width, height );
+
+ // Clear display
+ glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Setup projection matrix
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glOrtho( 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f );
+
+ // Setup modelview matrix
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Display title
+ glColor3f( 1.0f, 1.0f, 1.0f );
+ DrawImage( TEX_TITLE, 0.1f, 0.9f, 0.0f, 0.3f );
+
+ // Display menu
+ glColor3f( 1.0f, 1.0f, 0.0f );
+ DrawImage( TEX_MENU, 0.38f, 0.62f, 0.35f, 0.5f );
+
+ // Display instructions
+ glColor3f( 0.0f, 1.0f, 1.0f );
+ DrawImage( TEX_INSTR, 0.32f, 0.68f, 0.65f, 0.85f );
+
+ // Swap buffers
+ glfwSwapBuffers();
+
+ // Check for keys
+ if( glfwGetKey( 'Q' ) || !glfwGetWindowParam( GLFW_OPENED ) )
+ {
+ option = MENU_QUIT;
+ }
+ else if( glfwGetKey( GLFW_KEY_F1 ) )
+ {
+ option = MENU_PLAY;
+ }
+ else
+ {
+ option = MENU_NONE;
+ }
+
+ // To avoid horrible busy waiting, sleep for at least 20 ms
+ glfwSleep( 0.02 );
+ }
+ while( option == MENU_NONE );
+
+ // Disable sticky keys
+ glfwDisable( GLFW_STICKY_KEYS );
+
+ return option;
+}
+
+
+//========================================================================
+// NewGame() - Initialize a new game
+//========================================================================
+
+void NewGame( void )
+{
+ // Frame information
+ starttime = thistime = glfwGetTime();
+
+ // Camera information
+ camerapos = CAMERA_DEFAULT;
+
+ // Player 1 information
+ player1.ypos = 0.0;
+ player1.yspeed = 0.0;
+
+ // Player 2 information
+ player2.ypos = 0.0;
+ player2.yspeed = 0.0;
+
+ // Ball information
+ ball.xpos = -1.0 + PLAYER_XSIZE;
+ ball.ypos = player1.ypos;
+ ball.xspeed = 1.0;
+ ball.yspeed = 1.0;
+}
+
+
+//========================================================================
+// PlayerControl() - Player control
+//========================================================================
+
+void PlayerControl( void )
+{
+ float joy1pos[ 2 ], joy2pos[ 2 ];
+
+ // Get joystick X & Y axis positions
+ glfwGetJoystickPos( GLFW_JOYSTICK_1, joy1pos, 2 );
+ glfwGetJoystickPos( GLFW_JOYSTICK_2, joy2pos, 2 );
+
+ // Player 1 control
+ if( glfwGetKey( 'A' ) || joy1pos[ 1 ] > 0.2f )
+ {
+ player1.yspeed += dt * ACCELERATION;
+ if( player1.yspeed > MAX_SPEED )
+ {
+ player1.yspeed = MAX_SPEED;
+ }
+ }
+ else if( glfwGetKey( 'Z' ) || joy1pos[ 1 ] < -0.2f )
+ {
+ player1.yspeed -= dt * ACCELERATION;
+ if( player1.yspeed < -MAX_SPEED )
+ {
+ player1.yspeed = -MAX_SPEED;
+ }
+ }
+ else
+ {
+ player1.yspeed /= exp( DECELERATION * dt );
+ }
+
+ // Player 2 control
+ if( glfwGetKey( 'K' ) || joy2pos[ 1 ] > 0.2f )
+ {
+ player2.yspeed += dt * ACCELERATION;
+ if( player2.yspeed > MAX_SPEED )
+ {
+ player2.yspeed = MAX_SPEED;
+ }
+ }
+ else if( glfwGetKey( 'M' ) || joy2pos[ 1 ] < -0.2f )
+ {
+ player2.yspeed -= dt * ACCELERATION;
+ if( player2.yspeed < -MAX_SPEED )
+ {
+ player2.yspeed = -MAX_SPEED;
+ }
+ }
+ else
+ {
+ player2.yspeed /= exp( DECELERATION * dt );
+ }
+
+ // Update player 1 position
+ player1.ypos += dt * player1.yspeed;
+ if( player1.ypos > 1.0 - PLAYER_YSIZE )
+ {
+ player1.ypos = 1.0 - PLAYER_YSIZE;
+ player1.yspeed = 0.0;
+ }
+ else if( player1.ypos < -1.0 + PLAYER_YSIZE )
+ {
+ player1.ypos = -1.0 + PLAYER_YSIZE;
+ player1.yspeed = 0.0;
+ }
+
+ // Update player 2 position
+ player2.ypos += dt * player2.yspeed;
+ if( player2.ypos > 1.0 - PLAYER_YSIZE )
+ {
+ player2.ypos = 1.0 - PLAYER_YSIZE;
+ player2.yspeed = 0.0;
+ }
+ else if( player2.ypos < -1.0 + PLAYER_YSIZE )
+ {
+ player2.ypos = -1.0 + PLAYER_YSIZE;
+ player2.yspeed = 0.0;
+ }
+}
+
+
+//========================================================================
+// BallControl() - Ball control
+//========================================================================
+
+int BallControl( void )
+{
+ int event;
+ double ballspeed;
+
+ // Calculate new ball speed
+ ballspeed = BALL_SPEED * (1.0 + 0.02*(thistime-starttime));
+ ball.xspeed = ball.xspeed > 0 ? ballspeed : -ballspeed;
+ ball.yspeed = ball.yspeed > 0 ? ballspeed : -ballspeed;
+ ball.yspeed *= 0.74321;
+
+ // Update ball position
+ ball.xpos += dt * ball.xspeed;
+ ball.ypos += dt * ball.yspeed;
+
+ // Did the ball hit a top/bottom wall?
+ if( ball.ypos >= 1.0 )
+ {
+ ball.ypos = 2.0 - ball.ypos;
+ ball.yspeed = -ball.yspeed;
+ }
+ else if( ball.ypos <= -1.0 )
+ {
+ ball.ypos = -2.0 - ball.ypos;
+ ball.yspeed = -ball.yspeed;
+ }
+
+ // Did the ball hit/miss a player?
+ event = NOBODY_WINS;
+
+ // Is the ball entering the player 1 goal?
+ if( ball.xpos < -1.0 + PLAYER_XSIZE )
+ {
+ // Did player 1 catch the ball?
+ if( ball.ypos > (player1.ypos-PLAYER_YSIZE) &&
+ ball.ypos < (player1.ypos+PLAYER_YSIZE) )
+ {
+ ball.xpos = -2.0 + 2.0*PLAYER_XSIZE - ball.xpos;
+ ball.xspeed = -ball.xspeed;
+ }
+ else
+ {
+ event = PLAYER2_WINS;
+ }
+ }
+
+ // Is the ball entering the player 2 goal?
+ if( ball.xpos > 1.0 - PLAYER_XSIZE )
+ {
+ // Did player 2 catch the ball?
+ if( ball.ypos > (player2.ypos-PLAYER_YSIZE) &&
+ ball.ypos < (player2.ypos+PLAYER_YSIZE) )
+ {
+ ball.xpos = 2.0 - 2.0*PLAYER_XSIZE - ball.xpos;
+ ball.xspeed = -ball.xspeed;
+ }
+ else
+ {
+ event = PLAYER1_WINS;
+ }
+ }
+
+ return event;
+}
+
+
+//========================================================================
+// DrawBox() - Draw a 3D box
+//========================================================================
+
+#define TEX_SCALE 4.0f
+
+
+void DrawBox( float x1, float y1, float z1, float x2, float y2, float z2 )
+{
+ // Draw six sides of a cube
+ glBegin( GL_QUADS );
+ // Side 1 (down)
+ glNormal3f( 0.0f, 0.0f, -1.0f );
+ glTexCoord2f( 0.0f, 0.0f );
+ glVertex3f( x1,y2,z1 );
+ glTexCoord2f( TEX_SCALE, 0.0f );
+ glVertex3f( x2,y2,z1 );
+ glTexCoord2f( TEX_SCALE, TEX_SCALE );
+ glVertex3f( x2,y1,z1 );
+ glTexCoord2f( 0.0f, TEX_SCALE );
+ glVertex3f( x1,y1,z1 );
+ // Side 2 (up)
+ glNormal3f( 0.0f, 0.0f, 1.0f );
+ glTexCoord2f( 0.0f, 0.0f );
+ glVertex3f( x1,y1,z2 );
+ glTexCoord2f( TEX_SCALE, 0.0f );
+ glVertex3f( x2,y1,z2 );
+ glTexCoord2f( TEX_SCALE, TEX_SCALE );
+ glVertex3f( x2,y2,z2 );
+ glTexCoord2f( 0.0f, TEX_SCALE );
+ glVertex3f( x1,y2,z2 );
+ // Side 3 (backward)
+ glNormal3f( 0.0f, -1.0f, 0.0f );
+ glTexCoord2f( 0.0f, 0.0f );
+ glVertex3f( x1,y1,z1 );
+ glTexCoord2f( TEX_SCALE, 0.0f );
+ glVertex3f( x2,y1,z1 );
+ glTexCoord2f( TEX_SCALE, TEX_SCALE );
+ glVertex3f( x2,y1,z2 );
+ glTexCoord2f( 0.0f, TEX_SCALE );
+ glVertex3f( x1,y1,z2 );
+ // Side 4 (forward)
+ glNormal3f( 0.0f, 1.0f, 0.0f );
+ glTexCoord2f( 0.0f, 0.0f );
+ glVertex3f( x1,y2,z2 );
+ glTexCoord2f( TEX_SCALE, 0.0f );
+ glVertex3f( x2,y2,z2 );
+ glTexCoord2f( TEX_SCALE, TEX_SCALE );
+ glVertex3f( x2,y2,z1 );
+ glTexCoord2f( 0.0f, TEX_SCALE );
+ glVertex3f( x1,y2,z1 );
+ // Side 5 (left)
+ glNormal3f( -1.0f, 0.0f, 0.0f );
+ glTexCoord2f( 0.0f, 0.0f );
+ glVertex3f( x1,y1,z2 );
+ glTexCoord2f( TEX_SCALE, 0.0f );
+ glVertex3f( x1,y2,z2 );
+ glTexCoord2f( TEX_SCALE, TEX_SCALE );
+ glVertex3f( x1,y2,z1 );
+ glTexCoord2f( 0.0f, TEX_SCALE );
+ glVertex3f( x1,y1,z1 );
+ // Side 6 (right)
+ glNormal3f( 1.0f, 0.0f, 0.0f );
+ glTexCoord2f( 0.0f, 0.0f );
+ glVertex3f( x2,y1,z1 );
+ glTexCoord2f( TEX_SCALE, 0.0f );
+ glVertex3f( x2,y2,z1 );
+ glTexCoord2f( TEX_SCALE, TEX_SCALE );
+ glVertex3f( x2,y2,z2 );
+ glTexCoord2f( 0.0f, TEX_SCALE );
+ glVertex3f( x2,y1,z2 );
+ glEnd();
+}
+
+
+//========================================================================
+// UpdateDisplay() - Draw graphics (all game related OpenGL stuff goes
+// here)
+//========================================================================
+
+void UpdateDisplay( void )
+{
+ // Get window size
+ glfwGetWindowSize( &width, &height );
+
+ // Set viewport
+ glViewport( 0, 0, width, height );
+
+ // Clear display
+ glClearColor( 0.02f, 0.02f, 0.02f, 0.0f );
+ glClearDepth( 1.0f );
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+ // Setup projection matrix
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ gluPerspective(
+ 55.0f, // Angle of view
+ (GLfloat)width/(GLfloat)height, // Aspect
+ 1.0f, // Near Z
+ 100.0f // Far Z
+ );
+
+ // Setup modelview matrix
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ switch( camerapos )
+ {
+ default:
+ case CAMERA_CLASSIC:
+ gluLookAt(
+ 0.0f, 0.0f, 2.5f,
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f
+ );
+ break;
+ case CAMERA_ABOVE:
+ gluLookAt(
+ 0.0f, 0.0f, 2.5f,
+ (float)ball.xpos, (float)ball.ypos, 0.0f,
+ 0.0f, 1.0f, 0.0f
+ );
+ break;
+ case CAMERA_SPECTATOR:
+ gluLookAt(
+ 0.0f, -2.0, 1.2f,
+ (float)ball.xpos, (float)ball.ypos, 0.0f,
+ 0.0f, 0.0f, 1.0f
+ );
+ break;
+ }
+
+ // Enable depth testing
+ glEnable( GL_DEPTH_TEST );
+ glDepthFunc( GL_LEQUAL );
+
+ // Enable lighting
+ glEnable( GL_LIGHTING );
+ glLightModelfv( GL_LIGHT_MODEL_AMBIENT, env_ambient );
+ glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE );
+ glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE );
+ glLightfv( GL_LIGHT1, GL_POSITION, light1_position );
+ glLightfv( GL_LIGHT1, GL_DIFFUSE, light1_diffuse );
+ glLightfv( GL_LIGHT1, GL_AMBIENT, light1_ambient );
+ glEnable( GL_LIGHT1 );
+
+ // Front face is counter-clock-wise
+ glFrontFace( GL_CCW );
+
+ // Enable face culling (not necessary, but speeds up rendering)
+ glCullFace( GL_BACK );
+ glEnable( GL_CULL_FACE );
+
+ // Draw Player 1
+ glMaterialfv( GL_FRONT, GL_DIFFUSE, player1_diffuse );
+ glMaterialfv( GL_FRONT, GL_AMBIENT, player1_ambient );
+ DrawBox( -1.f, (GLfloat)player1.ypos-PLAYER_YSIZE, 0.f,
+ -1.f+PLAYER_XSIZE, (GLfloat)player1.ypos+PLAYER_YSIZE, 0.1f );
+
+ // Draw Player 2
+ glMaterialfv( GL_FRONT, GL_DIFFUSE, player2_diffuse );
+ glMaterialfv( GL_FRONT, GL_AMBIENT, player2_ambient );
+ DrawBox( 1.f-PLAYER_XSIZE, (GLfloat)player2.ypos-PLAYER_YSIZE, 0.f,
+ 1.f, (GLfloat)player2.ypos+PLAYER_YSIZE, 0.1f );
+
+ // Draw Ball
+ glMaterialfv( GL_FRONT, GL_DIFFUSE, ball_diffuse );
+ glMaterialfv( GL_FRONT, GL_AMBIENT, ball_ambient );
+ DrawBox( (GLfloat)ball.xpos-BALL_SIZE, (GLfloat)ball.ypos-BALL_SIZE, 0.f,
+ (GLfloat)ball.xpos+BALL_SIZE, (GLfloat)ball.ypos+BALL_SIZE, BALL_SIZE*2 );
+
+ // Top game field border
+ glMaterialfv( GL_FRONT, GL_DIFFUSE, border_diffuse );
+ glMaterialfv( GL_FRONT, GL_AMBIENT, border_ambient );
+ DrawBox( -1.1f, 1.0f, 0.0f, 1.1f, 1.1f, 0.1f );
+ // Bottom game field border
+ glColor3f( 0.0f, 0.0f, 0.7f );
+ DrawBox( -1.1f, -1.1f, 0.0f, 1.1f, -1.0f, 0.1f );
+ // Left game field border
+ DrawBox( -1.1f, -1.0f, 0.0f, -1.0f, 1.0f, 0.1f );
+ // Left game field border
+ DrawBox( 1.0f, -1.0f, 0.0f, 1.1f, 1.0f, 0.1f );
+
+ // Enable texturing
+ glEnable( GL_TEXTURE_2D );
+ glBindTexture( GL_TEXTURE_2D, tex_id[ TEX_FIELD ] );
+
+ // Game field floor
+ glMaterialfv( GL_FRONT, GL_DIFFUSE, floor_diffuse );
+ glMaterialfv( GL_FRONT, GL_AMBIENT, floor_ambient );
+ DrawBox( -1.01f, -1.01f, -0.01f, 1.01f, 1.01f, 0.0f );
+
+ // Disable texturing
+ glDisable( GL_TEXTURE_2D );
+
+ // Disable face culling
+ glDisable( GL_CULL_FACE );
+
+ // Disable lighting
+ glDisable( GL_LIGHTING );
+
+ // Disable depth testing
+ glDisable( GL_DEPTH_TEST );
+}
+
+
+//========================================================================
+// GameOver()
+//========================================================================
+
+void GameOver( void )
+{
+ // Enable sticky keys
+ glfwEnable( GLFW_STICKY_KEYS );
+
+ // Until the user presses ESC or SPACE
+ while( !glfwGetKey( GLFW_KEY_ESC ) && !glfwGetKey( ' ' ) &&
+ glfwGetWindowParam( GLFW_OPENED ) )
+ {
+ // Draw display
+ UpdateDisplay();
+
+ // Setup projection matrix
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glOrtho( 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f );
+
+ // Setup modelview matrix
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+
+ // Enable blending
+ glEnable( GL_BLEND );
+
+ // Dim background
+ glBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA );
+ glColor4f( 0.3f, 0.3f, 0.3f, 0.3f );
+ glBegin( GL_QUADS );
+ glVertex2f( 0.0f, 0.0f );
+ glVertex2f( 1.0f, 0.0f );
+ glVertex2f( 1.0f, 1.0f );
+ glVertex2f( 0.0f, 1.0f );
+ glEnd();
+
+ // Display winner text
+ glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_COLOR );
+ if( winner == PLAYER1 )
+ {
+ glColor4f( 1.0f, 0.5f, 0.5f, 1.0f );
+ DrawImage( TEX_WINNER1, 0.35f, 0.65f, 0.46f, 0.54f );
+ }
+ else if( winner == PLAYER2 )
+ {
+ glColor4f( 0.5f, 1.0f, 0.5f, 1.0f );
+ DrawImage( TEX_WINNER2, 0.35f, 0.65f, 0.46f, 0.54f );
+ }
+
+ // Disable blending
+ glDisable( GL_BLEND );
+
+ // Swap buffers
+ glfwSwapBuffers();
+ }
+
+ // Disable sticky keys
+ glfwDisable( GLFW_STICKY_KEYS );
+}
+
+
+//========================================================================
+// GameLoop() - Game loop
+//========================================================================
+
+void GameLoop( void )
+{
+ int playing, event;
+
+ // Initialize a new game
+ NewGame();
+
+ // Enable sticky keys
+ glfwEnable( GLFW_STICKY_KEYS );
+
+ // Loop until the game ends
+ playing = GL_TRUE;
+ while( playing && glfwGetWindowParam( GLFW_OPENED ) )
+ {
+ // Frame timer
+ oldtime = thistime;
+ thistime = glfwGetTime();
+ dt = thistime - oldtime;
+
+ // Get user input and update player positions
+ PlayerControl();
+
+ // Move the ball, and check if a player hits/misses the ball
+ event = BallControl();
+
+ // Did we have a winner?
+ switch( event )
+ {
+ case PLAYER1_WINS:
+ winner = PLAYER1;
+ playing = GL_FALSE;
+ break;
+ case PLAYER2_WINS:
+ winner = PLAYER2;
+ playing = GL_FALSE;
+ break;
+ default:
+ break;
+ }
+
+ // Did the user press ESC?
+ if( glfwGetKey( GLFW_KEY_ESC ) )
+ {
+ playing = GL_FALSE;
+ }
+
+ // Did the user change camera view?
+ if( glfwGetKey( '1' ) )
+ {
+ camerapos = CAMERA_CLASSIC;
+ }
+ else if( glfwGetKey( '2' ) )
+ {
+ camerapos = CAMERA_ABOVE;
+ }
+ else if( glfwGetKey( '3' ) )
+ {
+ camerapos = CAMERA_SPECTATOR;
+ }
+
+ // Draw display
+ UpdateDisplay();
+
+ // Swap buffers
+ glfwSwapBuffers();
+ }
+
+ // Disable sticky keys
+ glfwDisable( GLFW_STICKY_KEYS );
+
+ // Show winner
+ GameOver();
+}
+
+
+//========================================================================
+// main() - Program entry point
+//========================================================================
+
+int main( void )
+{
+ int menuoption;
+
+ // Initialize GLFW
+ if( !glfwInit() )
+ {
+ fprintf( stderr, "Failed to initialize GLFW\n" );
+ exit( EXIT_FAILURE );
+ }
+
+ // Open OpenGL window
+ if( !glfwOpenWindow( WIDTH, HEIGHT, 0,0,0,0, 16,0, GLFW_FULLSCREEN ) )
+ {
+ fprintf( stderr, "Failed to open GLFW window\n" );
+ glfwTerminate();
+ exit( EXIT_FAILURE );
+ }
+
+ glfwSwapInterval( 1 );
+
+ // Load all textures
+ if( !LoadTextures() )
+ {
+ glfwTerminate();
+ exit( EXIT_FAILURE );
+ }
+
+ // Main loop
+ do
+ {
+ // Get menu option
+ menuoption = GameMenu();
+
+ // If the user wants to play, let him...
+ if( menuoption == MENU_PLAY )
+ {
+ GameLoop();
+ }
+ }
+ while( menuoption != MENU_QUIT );
+
+ // Unload all textures
+ if( glfwGetWindowParam( GLFW_OPENED ) )
+ {
+ glDeleteTextures( NUM_TEXTURES, tex_id );
+ }
+
+ // Terminate GLFW
+ glfwTerminate();
+
+ exit( EXIT_SUCCESS );
+}
+
diff --git a/examples/pong3d_field.tga b/examples/pong3d_field.tga
new file mode 100644
index 00000000..cc20bbdb
Binary files /dev/null and b/examples/pong3d_field.tga differ
diff --git a/examples/pong3d_instr.tga b/examples/pong3d_instr.tga
new file mode 100644
index 00000000..758eb447
Binary files /dev/null and b/examples/pong3d_instr.tga differ
diff --git a/examples/pong3d_menu.tga b/examples/pong3d_menu.tga
new file mode 100644
index 00000000..d0d6c5a4
Binary files /dev/null and b/examples/pong3d_menu.tga differ
diff --git a/examples/pong3d_title.tga b/examples/pong3d_title.tga
new file mode 100644
index 00000000..d0d8e36d
Binary files /dev/null and b/examples/pong3d_title.tga differ
diff --git a/examples/pong3d_winner1.tga b/examples/pong3d_winner1.tga
new file mode 100644
index 00000000..f963720c
Binary files /dev/null and b/examples/pong3d_winner1.tga differ
diff --git a/examples/pong3d_winner2.tga b/examples/pong3d_winner2.tga
new file mode 100644
index 00000000..ea8266de
Binary files /dev/null and b/examples/pong3d_winner2.tga differ
diff --git a/examples/splitview.c b/examples/splitview.c
new file mode 100644
index 00000000..a26cd2c5
--- /dev/null
+++ b/examples/splitview.c
@@ -0,0 +1,514 @@
+//========================================================================
+// This is an example program for the GLFW library
+//
+// The program uses a "split window" view, rendering four views of the
+// same scene in one window (e.g. uesful for 3D modelling software). This
+// demo uses scissors to separete the four different rendering areas from
+// each other.
+//
+// (If the code seems a little bit strange here and there, it may be
+// because I am not a friend of orthogonal projections)
+//========================================================================
+
+#include
+#include
+#include
+#include
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+
+//========================================================================
+// Global variables
+//========================================================================
+
+// Mouse position
+static int xpos = 0, ypos = 0;
+
+// Window size
+static int width, height;
+
+// Active view: 0 = none, 1 = upper left, 2 = upper right, 3 = lower left,
+// 4 = lower right
+static int active_view = 0;
+
+// Rotation around each axis
+static int rot_x = 0, rot_y = 0, rot_z = 0;
+
+// Do redraw?
+static int do_redraw = 1;
+
+
+//========================================================================
+// Draw a solid torus (use a display list for the model)
+//========================================================================
+
+#define TORUS_MAJOR 1.5
+#define TORUS_MINOR 0.5
+#define TORUS_MAJOR_RES 32
+#define TORUS_MINOR_RES 32
+
+static void drawTorus( void )
+{
+ static GLuint torus_list = 0;
+ int i, j, k;
+ double s, t, x, y, z, nx, ny, nz, scale, twopi;
+
+ if( !torus_list )
+ {
+ // Start recording displaylist
+ torus_list = glGenLists( 1 );
+ glNewList( torus_list, GL_COMPILE_AND_EXECUTE );
+
+ // Draw torus
+ twopi = 2.0 * M_PI;
+ for( i = 0; i < TORUS_MINOR_RES; i++ )
+ {
+ glBegin( GL_QUAD_STRIP );
+ for( j = 0; j <= TORUS_MAJOR_RES; j++ )
+ {
+ for( k = 1; k >= 0; k-- )
+ {
+ s = (i + k) % TORUS_MINOR_RES + 0.5;
+ t = j % TORUS_MAJOR_RES;
+
+ // Calculate point on surface
+ x = (TORUS_MAJOR+TORUS_MINOR*cos(s*twopi/TORUS_MINOR_RES))*cos(t*twopi/TORUS_MAJOR_RES);
+ y = TORUS_MINOR * sin(s * twopi / TORUS_MINOR_RES);
+ z = (TORUS_MAJOR+TORUS_MINOR*cos(s*twopi/TORUS_MINOR_RES))*sin(t*twopi/TORUS_MAJOR_RES);
+
+ // Calculate surface normal
+ nx = x - TORUS_MAJOR*cos(t*twopi/TORUS_MAJOR_RES);
+ ny = y;
+ nz = z - TORUS_MAJOR*sin(t*twopi/TORUS_MAJOR_RES);
+ scale = 1.0 / sqrt( nx*nx + ny*ny + nz*nz );
+ nx *= scale;
+ ny *= scale;
+ nz *= scale;
+
+ glNormal3f( (float)nx, (float)ny, (float)nz );
+ glVertex3f( (float)x, (float)y, (float)z );
+ }
+ }
+ glEnd();
+ }
+
+ // Stop recording displaylist
+ glEndList();
+ }
+ else
+ {
+ // Playback displaylist
+ glCallList( torus_list );
+ }
+}
+
+
+//========================================================================
+// Draw the scene (a rotating torus)
+//========================================================================
+
+static void drawScene( void )
+{
+ const GLfloat model_diffuse[4] = {1.0f, 0.8f, 0.8f, 1.0f};
+ const GLfloat model_specular[4] = {0.6f, 0.6f, 0.6f, 1.0f};
+ const GLfloat model_shininess = 20.0f;
+
+ glPushMatrix();
+
+ // Rotate the object
+ glRotatef( (GLfloat)rot_x*0.5f, 1.0f, 0.0f, 0.0f );
+ glRotatef( (GLfloat)rot_y*0.5f, 0.0f, 1.0f, 0.0f );
+ glRotatef( (GLfloat)rot_z*0.5f, 0.0f, 0.0f, 1.0f );
+
+ // Set model color (used for orthogonal views, lighting disabled)
+ glColor4fv( model_diffuse );
+
+ // Set model material (used for perspective view, lighting enabled)
+ glMaterialfv( GL_FRONT, GL_DIFFUSE, model_diffuse );
+ glMaterialfv( GL_FRONT, GL_SPECULAR, model_specular );
+ glMaterialf( GL_FRONT, GL_SHININESS, model_shininess );
+
+ // Draw torus
+ drawTorus();
+
+ glPopMatrix();
+}
+
+
+//========================================================================
+// Draw a 2D grid (used for orthogonal views)
+//========================================================================
+
+static void drawGrid( float scale, int steps )
+{
+ int i;
+ float x, y;
+
+ glPushMatrix();
+
+ // Set background to some dark bluish grey
+ glClearColor( 0.05f, 0.05f, 0.2f, 0.0f);
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Setup modelview matrix (flat XY view)
+ glLoadIdentity();
+ gluLookAt( 0.0, 0.0, 1.0,
+ 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0 );
+
+ // We don't want to update the Z-buffer
+ glDepthMask( GL_FALSE );
+
+ // Set grid color
+ glColor3f( 0.0f, 0.5f, 0.5f );
+
+ glBegin( GL_LINES );
+
+ // Horizontal lines
+ x = scale * 0.5f * (float)(steps-1);
+ y = -scale * 0.5f * (float)(steps-1);
+ for( i = 0; i < steps; i ++ )
+ {
+ glVertex3f( -x, y, 0.0f );
+ glVertex3f( x, y, 0.0f );
+ y += scale;
+ }
+
+ // Vertical lines
+ x = -scale * 0.5f * (float)(steps-1);
+ y = scale * 0.5f * (float)(steps-1);
+ for( i = 0; i < steps; i ++ )
+ {
+ glVertex3f( x, -y, 0.0f );
+ glVertex3f( x, y, 0.0f );
+ x += scale;
+ }
+
+ glEnd();
+
+ // Enable Z-buffer writing again
+ glDepthMask( GL_TRUE );
+
+ glPopMatrix();
+}
+
+
+//========================================================================
+// Draw all views
+//========================================================================
+
+static void drawAllViews( void )
+{
+ const GLfloat light_position[4] = {0.0f, 8.0f, 8.0f, 1.0f};
+ const GLfloat light_diffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ const GLfloat light_specular[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ const GLfloat light_ambient[4] = {0.2f, 0.2f, 0.3f, 1.0f};
+ double aspect;
+
+ // Calculate aspect of window
+ if( height > 0 )
+ {
+ aspect = (double)width / (double)height;
+ }
+ else
+ {
+ aspect = 1.0;
+ }
+
+ // Clear screen
+ glClearColor( 0.0f, 0.0f, 0.0f, 0.0f);
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
+ // Enable scissor test
+ glEnable( GL_SCISSOR_TEST );
+
+ // Enable depth test
+ glEnable( GL_DEPTH_TEST );
+ glDepthFunc( GL_LEQUAL );
+
+
+ // ** ORTHOGONAL VIEWS **
+
+ // For orthogonal views, use wireframe rendering
+ glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+
+ // Enable line anti-aliasing
+ glEnable( GL_LINE_SMOOTH );
+ glEnable( GL_BLEND );
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+
+ // Setup orthogonal projection matrix
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glOrtho( -3.0*aspect, 3.0*aspect, -3.0, 3.0, 1.0, 50.0 );
+
+ // Upper left view (TOP VIEW)
+ glViewport( 0, height/2, width/2, height/2 );
+ glScissor( 0, height/2, width/2, height/2 );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ gluLookAt( 0.0f, 10.0f, 1e-3f, // Eye-position (above)
+ 0.0f, 0.0f, 0.0f, // View-point
+ 0.0f, 1.0f, 0.0f ); // Up-vector
+ drawGrid( 0.5, 12 );
+ drawScene();
+
+ // Lower left view (FRONT VIEW)
+ glViewport( 0, 0, width/2, height/2 );
+ glScissor( 0, 0, width/2, height/2 );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ gluLookAt( 0.0f, 0.0f, 10.0f, // Eye-position (in front of)
+ 0.0f, 0.0f, 0.0f, // View-point
+ 0.0f, 1.0f, 0.0f ); // Up-vector
+ drawGrid( 0.5, 12 );
+ drawScene();
+
+ // Lower right view (SIDE VIEW)
+ glViewport( width/2, 0, width/2, height/2 );
+ glScissor( width/2, 0, width/2, height/2 );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ gluLookAt( 10.0f, 0.0f, 0.0f, // Eye-position (to the right)
+ 0.0f, 0.0f, 0.0f, // View-point
+ 0.0f, 1.0f, 0.0f ); // Up-vector
+ drawGrid( 0.5, 12 );
+ drawScene();
+
+ // Disable line anti-aliasing
+ glDisable( GL_LINE_SMOOTH );
+ glDisable( GL_BLEND );
+
+
+ // ** PERSPECTIVE VIEW **
+
+ // For perspective view, use solid rendering
+ glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
+
+ // Enable face culling (faster rendering)
+ glEnable( GL_CULL_FACE );
+ glCullFace( GL_BACK );
+ glFrontFace( GL_CW );
+
+ // Setup perspective projection matrix
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ gluPerspective( 65.0f, aspect, 1.0f, 50.0f );
+
+ // Upper right view (PERSPECTIVE VIEW)
+ glViewport( width/2, height/2, width/2, height/2 );
+ glScissor( width/2, height/2, width/2, height/2 );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ gluLookAt( 3.0f, 1.5f, 3.0f, // Eye-position
+ 0.0f, 0.0f, 0.0f, // View-point
+ 0.0f, 1.0f, 0.0f ); // Up-vector
+
+ // Configure and enable light source 1
+ glLightfv( GL_LIGHT1, GL_POSITION, light_position );
+ glLightfv( GL_LIGHT1, GL_AMBIENT, light_ambient );
+ glLightfv( GL_LIGHT1, GL_DIFFUSE, light_diffuse );
+ glLightfv( GL_LIGHT1, GL_SPECULAR, light_specular );
+ glEnable( GL_LIGHT1 );
+ glEnable( GL_LIGHTING );
+
+ // Draw scene
+ drawScene();
+
+ // Disable lighting
+ glDisable( GL_LIGHTING );
+
+ // Disable face culling
+ glDisable( GL_CULL_FACE );
+
+ // Disable depth test
+ glDisable( GL_DEPTH_TEST );
+
+ // Disable scissor test
+ glDisable( GL_SCISSOR_TEST );
+
+
+ // Draw a border around the active view
+ if( active_view > 0 && active_view != 2 )
+ {
+ glViewport( 0, 0, width, height );
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glOrtho( 0.0, 2.0, 0.0, 2.0, 0.0, 1.0 );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ glColor3f( 1.0f, 1.0f, 0.6f );
+ glTranslatef( (GLfloat) ((active_view - 1) & 1), (GLfloat) (1 - (active_view - 1) / 2), 0.0f );
+ glBegin( GL_LINE_STRIP );
+ glVertex2i( 0, 0 );
+ glVertex2i( 1, 0 );
+ glVertex2i( 1, 1 );
+ glVertex2i( 0, 1 );
+ glVertex2i( 0, 0 );
+ glEnd();
+ }
+}
+
+
+//========================================================================
+// Window size callback function
+//========================================================================
+
+static void windowSizeFun( int w, int h )
+{
+ width = w;
+ height = h > 0 ? h : 1;
+ do_redraw = 1;
+}
+
+
+//========================================================================
+// Window refresh callback function
+//========================================================================
+
+static void windowRefreshFun( void )
+{
+ do_redraw = 1;
+}
+
+
+//========================================================================
+// Mouse position callback function
+//========================================================================
+
+static void mousePosFun( int x, int y )
+{
+ // Depending on which view was selected, rotate around different axes
+ switch( active_view )
+ {
+ case 1:
+ rot_x += y - ypos;
+ rot_z += x - xpos;
+ do_redraw = 1;
+ break;
+ case 3:
+ rot_x += y - ypos;
+ rot_y += x - xpos;
+ do_redraw = 1;
+ break;
+ case 4:
+ rot_y += x - xpos;
+ rot_z += y - ypos;
+ do_redraw = 1;
+ break;
+ default:
+ // Do nothing for perspective view, or if no view is selected
+ break;
+ }
+
+ // Remember mouse position
+ xpos = x;
+ ypos = y;
+}
+
+
+//========================================================================
+// Mouse button callback function
+//========================================================================
+
+static void mouseButtonFun( int button, int action )
+{
+ // Button clicked?
+ if( ( button == GLFW_MOUSE_BUTTON_LEFT ) && action == GLFW_PRESS )
+ {
+ // Detect which of the four views was clicked
+ active_view = 1;
+ if( xpos >= width/2 )
+ {
+ active_view += 1;
+ }
+ if( ypos >= height/2 )
+ {
+ active_view += 2;
+ }
+ }
+
+ // Button released?
+ else if( button == GLFW_MOUSE_BUTTON_LEFT )
+ {
+ // Deselect any previously selected view
+ active_view = 0;
+ }
+
+ do_redraw = 1;
+}
+
+
+//========================================================================
+// main()
+//========================================================================
+
+int main( void )
+{
+ // Initialise GLFW
+ if( !glfwInit() )
+ {
+ fprintf( stderr, "Failed to initialize GLFW\n" );
+ exit( EXIT_FAILURE );
+ }
+
+ // Open OpenGL window
+ if( !glfwOpenWindow( 500, 500, 0,0,0,0, 16,0, GLFW_WINDOW ) )
+ {
+ fprintf( stderr, "Failed to open GLFW window\n" );
+ glfwTerminate();
+ exit( EXIT_FAILURE );
+ }
+
+ // Enable vsync
+ glfwSwapInterval( 1 );
+
+ // Set window title
+ glfwSetWindowTitle( "Split view demo" );
+
+ // Enable sticky keys
+ glfwEnable( GLFW_STICKY_KEYS );
+
+ // Enable mouse cursor (only needed for fullscreen mode)
+ glfwEnable( GLFW_MOUSE_CURSOR );
+
+ // Disable automatic event polling
+ glfwDisable( GLFW_AUTO_POLL_EVENTS );
+
+ // Set callback functions
+ glfwSetWindowSizeCallback( windowSizeFun );
+ glfwSetWindowRefreshCallback( windowRefreshFun );
+ glfwSetMousePosCallback( mousePosFun );
+ glfwSetMouseButtonCallback( mouseButtonFun );
+
+ // Main loop
+ do
+ {
+ // Only redraw if we need to
+ if( do_redraw )
+ {
+ // Draw all views
+ drawAllViews();
+
+ // Swap buffers
+ glfwSwapBuffers();
+
+ do_redraw = 0;
+ }
+
+ // Wait for new events
+ glfwWaitEvents();
+
+ } // Check if the ESC key was pressed or the window was closed
+ while( glfwGetKey( GLFW_KEY_ESC ) != GLFW_PRESS &&
+ glfwGetWindowParam( GLFW_OPENED ) );
+
+ // Close OpenGL window and terminate GLFW
+ glfwTerminate();
+
+ exit( EXIT_SUCCESS );
+}
+
diff --git a/examples/triangle.c b/examples/triangle.c
new file mode 100644
index 00000000..a8b737be
--- /dev/null
+++ b/examples/triangle.c
@@ -0,0 +1,94 @@
+//========================================================================
+// This is a small test application for GLFW.
+// The program opens a window (640x480), and renders a spinning colored
+// triangle (it is controlled with both the GLFW timer and the mouse).
+//========================================================================
+
+#include
+#include
+#include
+
+
+int main( void )
+{
+ int width, height, x;
+ double t;
+
+ // Initialise GLFW
+ if( !glfwInit() )
+ {
+ fprintf( stderr, "Failed to initialize GLFW\n" );
+ exit( EXIT_FAILURE );
+ }
+
+ // Open a window and create its OpenGL context
+ if( !glfwOpenWindow( 640, 480, 0,0,0,0, 0,0, GLFW_WINDOW ) )
+ {
+ fprintf( stderr, "Failed to open GLFW window\n" );
+
+ glfwTerminate();
+ exit( EXIT_FAILURE );
+ }
+
+ glfwSetWindowTitle( "Spinning Triangle" );
+
+ // Ensure we can capture the escape key being pressed below
+ glfwEnable( GLFW_STICKY_KEYS );
+
+ // Enable vertical sync (on cards that support it)
+ glfwSwapInterval( 1 );
+
+ do
+ {
+ t = glfwGetTime();
+ glfwGetMousePos( &x, NULL );
+
+ // Get window size (may be different than the requested size)
+ glfwGetWindowSize( &width, &height );
+
+ // Special case: avoid division by zero below
+ height = height > 0 ? height : 1;
+
+ glViewport( 0, 0, width, height );
+
+ // Clear color buffer to black
+ glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ // Select and setup the projection matrix
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ gluPerspective( 65.0f, (GLfloat)width/(GLfloat)height, 1.0f, 100.0f );
+
+ // Select and setup the modelview matrix
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ gluLookAt( 0.0f, 1.0f, 0.0f, // Eye-position
+ 0.0f, 20.0f, 0.0f, // View-point
+ 0.0f, 0.0f, 1.0f ); // Up-vector
+
+ // Draw a rotating colorful triangle
+ glTranslatef( 0.0f, 14.0f, 0.0f );
+ glRotatef( 0.3f*(GLfloat)x + (GLfloat)t*100.0f, 0.0f, 0.0f, 1.0f );
+ glBegin( GL_TRIANGLES );
+ glColor3f( 1.0f, 0.0f, 0.0f );
+ glVertex3f( -5.0f, 0.0f, -4.0f );
+ glColor3f( 0.0f, 1.0f, 0.0f );
+ glVertex3f( 5.0f, 0.0f, -4.0f );
+ glColor3f( 0.0f, 0.0f, 1.0f );
+ glVertex3f( 0.0f, 0.0f, 6.0f );
+ glEnd();
+
+ // Swap buffers
+ glfwSwapBuffers();
+
+ } // Check if the ESC key was pressed or the window was closed
+ while( glfwGetKey( GLFW_KEY_ESC ) != GLFW_PRESS &&
+ glfwGetWindowParam( GLFW_OPENED ) );
+
+ // Close OpenGL window and terminate GLFW
+ glfwTerminate();
+
+ exit( EXIT_SUCCESS );
+}
+
diff --git a/examples/wave.c b/examples/wave.c
new file mode 100644
index 00000000..571cc9d5
--- /dev/null
+++ b/examples/wave.c
@@ -0,0 +1,399 @@
+/*****************************************************************************
+ * Wave Simulation in OpenGL
+ * (C) 2002 Jakob Thomsen
+ * http://home.in.tum.de/~thomsen
+ * Modified for GLFW by Sylvain Hellegouarch - sh@programmationworld.com
+ * Modified for variable frame rate by Marcus Geelnard
+ * 2003-Jan-31: Minor cleanups and speedups / MG
+ *****************************************************************************/
+
+#include
+#include
+#include
+#include
+
+#ifndef M_PI
+ #define M_PI 3.1415926535897932384626433832795
+#endif
+
+/* Maximum delta T to allow for differential calculations */
+#define MAX_DELTA_T 0.01
+
+/* Animation speed (10.0 looks good) */
+#define ANIMATION_SPEED 10.0
+
+
+GLfloat alpha = 210.0f, beta = -70.0f;
+GLfloat zoom = 2.0f;
+
+int running = 1;
+
+struct Vertex
+{
+ GLfloat x,y,z;
+ GLfloat r,g,b;
+};
+
+#define GRIDW 50
+#define GRIDH 50
+#define VERTEXNUM (GRIDW*GRIDH)
+
+#define QUADW (GRIDW-1)
+#define QUADH (GRIDH-1)
+#define QUADNUM (QUADW*QUADH)
+
+GLuint quad[4*QUADNUM];
+struct Vertex vertex[VERTEXNUM];
+
+/* The grid will look like this:
+ *
+ * 3 4 5
+ * *---*---*
+ * | | |
+ * | 0 | 1 |
+ * | | |
+ * *---*---*
+ * 0 1 2
+ */
+
+void initVertices( void )
+{
+ int x,y,p;
+
+ /* place the vertices in a grid */
+ for(y=0;y1) zoom-=1;
+ break;
+ case GLFW_KEY_PAGEDOWN:
+ zoom+=1;
+ break;
+ default:
+ break;
+ }
+}
+
+
+/* Callback function for window resize events */
+void handle_resize( int width, int height )
+{
+ float ratio = 1.0f;
+
+ if( height > 0 )
+ {
+ ratio = (float) width / (float) height;
+ }
+
+ /* Setup viewport (Place where the stuff will appear in the main window). */
+ glViewport(0, 0, width, height);
+
+ /*
+ * Change to the projection matrix and set
+ * our viewing volume.
+ */
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(60.0, ratio, 1.0, 1024.0);
+}
+
+
+/* Program entry point */
+int main(int argc, char* argv[])
+{
+ /* Dimensions of our window. */
+ int width, height;
+ /* Style of our window. */
+ int mode;
+ /* Frame time */
+ double t, t_old, dt_total;
+
+ /* Initialize GLFW */
+ if(glfwInit() == GL_FALSE)
+ {
+ fprintf(stderr, "GLFW initialization failed\n");
+ exit(-1);
+ }
+
+ /* Desired window properties */
+ width = 640;
+ height = 480;
+ mode = GLFW_WINDOW;
+
+ /* Open window */
+ if( glfwOpenWindow(width,height,0,0,0,0,16,0,mode) == GL_FALSE )
+ {
+ fprintf(stderr, "Could not open window\n");
+ glfwTerminate();
+ exit(-1);
+ }
+
+ /* Set title */
+ glfwSetWindowTitle( "Wave Simulation" );
+
+ glfwSwapInterval( 1 );
+
+ /* Keyboard handler */
+ glfwSetKeyCallback( handle_key_down );
+ glfwEnable( GLFW_KEY_REPEAT );
+
+ /* Window resize handler */
+ glfwSetWindowSizeCallback( handle_resize );
+
+ /* Initialize OpenGL */
+ setup_opengl();
+
+ /* Initialize simulation */
+ initVertices();
+ initSurface();
+ adjustGrid();
+
+ /* Initialize timer */
+ t_old = glfwGetTime() - 0.01;
+
+ /* Main loop */
+ while(running)
+ {
+ /* Timing */
+ t = glfwGetTime();
+ dt_total = t - t_old;
+ t_old = t;
+
+ /* Safety - iterate if dt_total is too large */
+ while( dt_total > 0.0f )
+ {
+ /* Select iteration time step */
+ dt = dt_total > MAX_DELTA_T ? MAX_DELTA_T : dt_total;
+ dt_total -= dt;
+
+ /* Calculate wave propagation */
+ calc();
+ }
+
+ /* Compute height of each vertex */
+ adjustGrid();
+
+ /* Draw wave grid to OpenGL display */
+ draw_screen();
+
+ /* Still running? */
+ running = running && glfwGetWindowParam( GLFW_OPENED );
+ }
+
+ glfwTerminate();
+
+ return 0;
+}
diff --git a/include/GL/glfw.h b/include/GL/glfw.h
new file mode 100644
index 00000000..63313db3
--- /dev/null
+++ b/include/GL/glfw.h
@@ -0,0 +1,446 @@
+/************************************************************************
+ * GLFW - An OpenGL framework
+ * API version: 2.7
+ * WWW: http://www.glfw.org/
+ *------------------------------------------------------------------------
+ * Copyright (c) 2002-2006 Marcus Geelnard
+ * Copyright (c) 2006-2010 Camilla Berglund
+ *
+ * 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 __glfw_h_
+#define __glfw_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*************************************************************************
+ * Global definitions
+ *************************************************************************/
+
+/* We need a NULL pointer from time to time */
+#ifndef NULL
+ #ifdef __cplusplus
+ #define NULL 0
+ #else
+ #define NULL ((void *)0)
+ #endif
+#endif /* NULL */
+
+
+/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */
+
+/* Please report any probles that you find with your compiler, which may
+ * be solved in this section! There are several compilers that I have not
+ * been able to test this file with yet.
+ *
+ * First: If we are we on Windows, we want a single define for it (_WIN32)
+ * (Note: For Cygwin the compiler flag -mwin32 should be used, but to
+ * make sure that things run smoothly for Cygwin users, we add __CYGWIN__
+ * to the list of "valid Win32 identifiers", which removes the need for
+ * -mwin32)
+ */
+#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__))
+ #define _WIN32
+#endif /* _WIN32 */
+
+/* In order for extension support to be portable, we need to define an
+ * OpenGL function call method. We use the keyword APIENTRY, which is
+ * defined for Win32. (Note: Windows also needs this for )
+ */
+#ifndef APIENTRY
+ #ifdef _WIN32
+ #define APIENTRY __stdcall
+ #else
+ #define APIENTRY
+ #endif
+ #define GL_APIENTRY_DEFINED
+#endif /* APIENTRY */
+
+
+/* The following three defines are here solely to make some Windows-based
+ * files happy. Theoretically we could include , but
+ * it has the major drawback of severely polluting our namespace.
+ */
+
+/* Under Windows, we need WINGDIAPI defined */
+#if !defined(WINGDIAPI) && defined(_WIN32)
+ #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__)
+ /* Microsoft Visual C++, Borland C++ Builder and Pelles C */
+ #define WINGDIAPI __declspec(dllimport)
+ #elif defined(__LCC__)
+ /* LCC-Win32 */
+ #define WINGDIAPI __stdcall
+ #else
+ /* Others (e.g. MinGW, Cygwin) */
+ #define WINGDIAPI extern
+ #endif
+ #define GL_WINGDIAPI_DEFINED
+#endif /* WINGDIAPI */
+
+/* Some files also need CALLBACK defined */
+#if !defined(CALLBACK) && defined(_WIN32)
+ #if defined(_MSC_VER)
+ /* Microsoft Visual C++ */
+ #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS)
+ #define CALLBACK __stdcall
+ #else
+ #define CALLBACK
+ #endif
+ #else
+ /* Other Windows compilers */
+ #define CALLBACK __stdcall
+ #endif
+ #define GLU_CALLBACK_DEFINED
+#endif /* CALLBACK */
+
+/* Microsoft Visual C++, Borland C++ and Pelles C needs wchar_t */
+#if defined(_WIN32) && (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__)) && !defined(_WCHAR_T_DEFINED)
+ typedef unsigned short wchar_t;
+ #define _WCHAR_T_DEFINED
+#endif /* _WCHAR_T_DEFINED */
+
+
+/* ---------------- GLFW related system specific defines ----------------- */
+
+#if defined(_WIN32) && defined(GLFW_BUILD_DLL)
+
+ /* We are building a Win32 DLL */
+ #define GLFWAPI __declspec(dllexport)
+
+#elif defined(_WIN32) && defined(GLFW_DLL)
+
+ /* We are calling a Win32 DLL */
+ #if defined(__LCC__)
+ #define GLFWAPI extern
+ #else
+ #define GLFWAPI __declspec(dllimport)
+ #endif
+
+#else
+
+ /* We are either building/calling a static lib or we are non-win32 */
+ #define GLFWAPI
+
+#endif
+
+/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */
+
+/* Include standard OpenGL headers: GLFW uses GL_FALSE/GL_TRUE, and it is
+ * convenient for the user to only have to include . This also
+ * solves the problem with Windows and needing some
+ * special defines which normally requires the user to include
+ * (which is not a nice solution for portable programs).
+ */
+#if defined(__APPLE_CC__)
+ #include
+ #ifndef GLFW_NO_GLU
+ #include
+ #endif
+#else
+ #include
+ #ifndef GLFW_NO_GLU
+ #include
+ #endif
+#endif
+
+
+/*************************************************************************
+ * GLFW version
+ *************************************************************************/
+
+#define GLFW_VERSION_MAJOR 2
+#define GLFW_VERSION_MINOR 7
+#define GLFW_VERSION_REVISION 0
+
+
+/*************************************************************************
+ * Input handling definitions
+ *************************************************************************/
+
+/* Key and button state/action definitions */
+#define GLFW_RELEASE 0
+#define GLFW_PRESS 1
+
+/* Keyboard key definitions: 8-bit ISO-8859-1 (Latin 1) encoding is used
+ * for printable keys (such as A-Z, 0-9 etc), and values above 256
+ * represent special (non-printable) keys (e.g. F1, Page Up etc).
+ */
+#define GLFW_KEY_UNKNOWN -1
+#define GLFW_KEY_SPACE 32
+#define GLFW_KEY_SPECIAL 256
+#define GLFW_KEY_ESC (GLFW_KEY_SPECIAL+1)
+#define GLFW_KEY_F1 (GLFW_KEY_SPECIAL+2)
+#define GLFW_KEY_F2 (GLFW_KEY_SPECIAL+3)
+#define GLFW_KEY_F3 (GLFW_KEY_SPECIAL+4)
+#define GLFW_KEY_F4 (GLFW_KEY_SPECIAL+5)
+#define GLFW_KEY_F5 (GLFW_KEY_SPECIAL+6)
+#define GLFW_KEY_F6 (GLFW_KEY_SPECIAL+7)
+#define GLFW_KEY_F7 (GLFW_KEY_SPECIAL+8)
+#define GLFW_KEY_F8 (GLFW_KEY_SPECIAL+9)
+#define GLFW_KEY_F9 (GLFW_KEY_SPECIAL+10)
+#define GLFW_KEY_F10 (GLFW_KEY_SPECIAL+11)
+#define GLFW_KEY_F11 (GLFW_KEY_SPECIAL+12)
+#define GLFW_KEY_F12 (GLFW_KEY_SPECIAL+13)
+#define GLFW_KEY_F13 (GLFW_KEY_SPECIAL+14)
+#define GLFW_KEY_F14 (GLFW_KEY_SPECIAL+15)
+#define GLFW_KEY_F15 (GLFW_KEY_SPECIAL+16)
+#define GLFW_KEY_F16 (GLFW_KEY_SPECIAL+17)
+#define GLFW_KEY_F17 (GLFW_KEY_SPECIAL+18)
+#define GLFW_KEY_F18 (GLFW_KEY_SPECIAL+19)
+#define GLFW_KEY_F19 (GLFW_KEY_SPECIAL+20)
+#define GLFW_KEY_F20 (GLFW_KEY_SPECIAL+21)
+#define GLFW_KEY_F21 (GLFW_KEY_SPECIAL+22)
+#define GLFW_KEY_F22 (GLFW_KEY_SPECIAL+23)
+#define GLFW_KEY_F23 (GLFW_KEY_SPECIAL+24)
+#define GLFW_KEY_F24 (GLFW_KEY_SPECIAL+25)
+#define GLFW_KEY_F25 (GLFW_KEY_SPECIAL+26)
+#define GLFW_KEY_UP (GLFW_KEY_SPECIAL+27)
+#define GLFW_KEY_DOWN (GLFW_KEY_SPECIAL+28)
+#define GLFW_KEY_LEFT (GLFW_KEY_SPECIAL+29)
+#define GLFW_KEY_RIGHT (GLFW_KEY_SPECIAL+30)
+#define GLFW_KEY_LSHIFT (GLFW_KEY_SPECIAL+31)
+#define GLFW_KEY_RSHIFT (GLFW_KEY_SPECIAL+32)
+#define GLFW_KEY_LCTRL (GLFW_KEY_SPECIAL+33)
+#define GLFW_KEY_RCTRL (GLFW_KEY_SPECIAL+34)
+#define GLFW_KEY_LALT (GLFW_KEY_SPECIAL+35)
+#define GLFW_KEY_RALT (GLFW_KEY_SPECIAL+36)
+#define GLFW_KEY_TAB (GLFW_KEY_SPECIAL+37)
+#define GLFW_KEY_ENTER (GLFW_KEY_SPECIAL+38)
+#define GLFW_KEY_BACKSPACE (GLFW_KEY_SPECIAL+39)
+#define GLFW_KEY_INSERT (GLFW_KEY_SPECIAL+40)
+#define GLFW_KEY_DEL (GLFW_KEY_SPECIAL+41)
+#define GLFW_KEY_PAGEUP (GLFW_KEY_SPECIAL+42)
+#define GLFW_KEY_PAGEDOWN (GLFW_KEY_SPECIAL+43)
+#define GLFW_KEY_HOME (GLFW_KEY_SPECIAL+44)
+#define GLFW_KEY_END (GLFW_KEY_SPECIAL+45)
+#define GLFW_KEY_KP_0 (GLFW_KEY_SPECIAL+46)
+#define GLFW_KEY_KP_1 (GLFW_KEY_SPECIAL+47)
+#define GLFW_KEY_KP_2 (GLFW_KEY_SPECIAL+48)
+#define GLFW_KEY_KP_3 (GLFW_KEY_SPECIAL+49)
+#define GLFW_KEY_KP_4 (GLFW_KEY_SPECIAL+50)
+#define GLFW_KEY_KP_5 (GLFW_KEY_SPECIAL+51)
+#define GLFW_KEY_KP_6 (GLFW_KEY_SPECIAL+52)
+#define GLFW_KEY_KP_7 (GLFW_KEY_SPECIAL+53)
+#define GLFW_KEY_KP_8 (GLFW_KEY_SPECIAL+54)
+#define GLFW_KEY_KP_9 (GLFW_KEY_SPECIAL+55)
+#define GLFW_KEY_KP_DIVIDE (GLFW_KEY_SPECIAL+56)
+#define GLFW_KEY_KP_MULTIPLY (GLFW_KEY_SPECIAL+57)
+#define GLFW_KEY_KP_SUBTRACT (GLFW_KEY_SPECIAL+58)
+#define GLFW_KEY_KP_ADD (GLFW_KEY_SPECIAL+59)
+#define GLFW_KEY_KP_DECIMAL (GLFW_KEY_SPECIAL+60)
+#define GLFW_KEY_KP_EQUAL (GLFW_KEY_SPECIAL+61)
+#define GLFW_KEY_KP_ENTER (GLFW_KEY_SPECIAL+62)
+#define GLFW_KEY_KP_NUM_LOCK (GLFW_KEY_SPECIAL+63)
+#define GLFW_KEY_CAPS_LOCK (GLFW_KEY_SPECIAL+64)
+#define GLFW_KEY_SCROLL_LOCK (GLFW_KEY_SPECIAL+65)
+#define GLFW_KEY_PAUSE (GLFW_KEY_SPECIAL+66)
+#define GLFW_KEY_LSUPER (GLFW_KEY_SPECIAL+67)
+#define GLFW_KEY_RSUPER (GLFW_KEY_SPECIAL+68)
+#define GLFW_KEY_MENU (GLFW_KEY_SPECIAL+69)
+#define GLFW_KEY_LAST GLFW_KEY_MENU
+
+/* Mouse button definitions */
+#define GLFW_MOUSE_BUTTON_1 0
+#define GLFW_MOUSE_BUTTON_2 1
+#define GLFW_MOUSE_BUTTON_3 2
+#define GLFW_MOUSE_BUTTON_4 3
+#define GLFW_MOUSE_BUTTON_5 4
+#define GLFW_MOUSE_BUTTON_6 5
+#define GLFW_MOUSE_BUTTON_7 6
+#define GLFW_MOUSE_BUTTON_8 7
+#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8
+
+/* Mouse button aliases */
+#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1
+#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2
+#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3
+
+/* Joystick identifiers */
+#define GLFW_JOYSTICK_1 0
+#define GLFW_JOYSTICK_2 1
+#define GLFW_JOYSTICK_3 2
+#define GLFW_JOYSTICK_4 3
+#define GLFW_JOYSTICK_5 4
+#define GLFW_JOYSTICK_6 5
+#define GLFW_JOYSTICK_7 6
+#define GLFW_JOYSTICK_8 7
+#define GLFW_JOYSTICK_9 8
+#define GLFW_JOYSTICK_10 9
+#define GLFW_JOYSTICK_11 10
+#define GLFW_JOYSTICK_12 11
+#define GLFW_JOYSTICK_13 12
+#define GLFW_JOYSTICK_14 13
+#define GLFW_JOYSTICK_15 14
+#define GLFW_JOYSTICK_16 15
+#define GLFW_JOYSTICK_LAST GLFW_JOYSTICK_16
+
+
+/*************************************************************************
+ * Other definitions
+ *************************************************************************/
+
+/* glfwOpenWindow modes */
+#define GLFW_WINDOW 0x00010001
+#define GLFW_FULLSCREEN 0x00010002
+
+/* glfwGetWindowParam tokens */
+#define GLFW_OPENED 0x00020001
+#define GLFW_ACTIVE 0x00020002
+#define GLFW_ICONIFIED 0x00020003
+#define GLFW_ACCELERATED 0x00020004
+#define GLFW_RED_BITS 0x00020005
+#define GLFW_GREEN_BITS 0x00020006
+#define GLFW_BLUE_BITS 0x00020007
+#define GLFW_ALPHA_BITS 0x00020008
+#define GLFW_DEPTH_BITS 0x00020009
+#define GLFW_STENCIL_BITS 0x0002000A
+
+/* The following constants are used for both glfwGetWindowParam
+ * and glfwOpenWindowHint
+ */
+#define GLFW_REFRESH_RATE 0x0002000B
+#define GLFW_ACCUM_RED_BITS 0x0002000C
+#define GLFW_ACCUM_GREEN_BITS 0x0002000D
+#define GLFW_ACCUM_BLUE_BITS 0x0002000E
+#define GLFW_ACCUM_ALPHA_BITS 0x0002000F
+#define GLFW_AUX_BUFFERS 0x00020010
+#define GLFW_STEREO 0x00020011
+#define GLFW_WINDOW_NO_RESIZE 0x00020012
+#define GLFW_FSAA_SAMPLES 0x00020013
+#define GLFW_OPENGL_VERSION_MAJOR 0x00020014
+#define GLFW_OPENGL_VERSION_MINOR 0x00020015
+#define GLFW_OPENGL_FORWARD_COMPAT 0x00020016
+#define GLFW_OPENGL_DEBUG_CONTEXT 0x00020017
+#define GLFW_OPENGL_PROFILE 0x00020018
+
+/* GLFW_OPENGL_PROFILE tokens */
+#define GLFW_OPENGL_CORE_PROFILE 0x00050001
+#define GLFW_OPENGL_COMPAT_PROFILE 0x00050002
+
+/* glfwEnable/glfwDisable tokens */
+#define GLFW_MOUSE_CURSOR 0x00030001
+#define GLFW_STICKY_KEYS 0x00030002
+#define GLFW_STICKY_MOUSE_BUTTONS 0x00030003
+#define GLFW_SYSTEM_KEYS 0x00030004
+#define GLFW_KEY_REPEAT 0x00030005
+#define GLFW_AUTO_POLL_EVENTS 0x00030006
+
+/* glfwGetJoystickParam tokens */
+#define GLFW_PRESENT 0x00050001
+#define GLFW_AXES 0x00050002
+#define GLFW_BUTTONS 0x00050003
+
+
+/*************************************************************************
+ * Typedefs
+ *************************************************************************/
+
+/* The video mode structure used by glfwGetVideoModes() */
+typedef struct {
+ int Width, Height;
+ int RedBits, BlueBits, GreenBits;
+} GLFWvidmode;
+
+/* Function pointer types */
+typedef void (* GLFWwindowsizefun)(int,int);
+typedef int (* GLFWwindowclosefun)(void);
+typedef void (* GLFWwindowrefreshfun)(void);
+typedef void (* GLFWmousebuttonfun)(int,int);
+typedef void (* GLFWmouseposfun)(int,int);
+typedef void (* GLFWmousewheelfun)(int);
+typedef void (* GLFWkeyfun)(int,int);
+typedef void (* GLFWcharfun)(int,int);
+
+
+/*************************************************************************
+ * Prototypes
+ *************************************************************************/
+
+/* GLFW initialization, termination and version querying */
+GLFWAPI int glfwInit( void );
+GLFWAPI void glfwTerminate( void );
+GLFWAPI void glfwGetVersion( int *major, int *minor, int *rev );
+
+/* Window handling */
+GLFWAPI int glfwOpenWindow( int width, int height, int redbits, int greenbits, int bluebits, int alphabits, int depthbits, int stencilbits, int mode );
+GLFWAPI void glfwOpenWindowHint( int target, int hint );
+GLFWAPI void glfwCloseWindow( void );
+GLFWAPI void glfwSetWindowTitle( const char *title );
+GLFWAPI void glfwGetWindowSize( int *width, int *height );
+GLFWAPI void glfwSetWindowSize( int width, int height );
+GLFWAPI void glfwSetWindowPos( int x, int y );
+GLFWAPI void glfwIconifyWindow( void );
+GLFWAPI void glfwRestoreWindow( void );
+GLFWAPI void glfwSwapBuffers( void );
+GLFWAPI void glfwSwapInterval( int interval );
+GLFWAPI int glfwGetWindowParam( int param );
+GLFWAPI void glfwSetWindowSizeCallback( GLFWwindowsizefun cbfun );
+GLFWAPI void glfwSetWindowCloseCallback( GLFWwindowclosefun cbfun );
+GLFWAPI void glfwSetWindowRefreshCallback( GLFWwindowrefreshfun cbfun );
+
+/* Video mode functions */
+GLFWAPI int glfwGetVideoModes( GLFWvidmode *list, int maxcount );
+GLFWAPI void glfwGetDesktopMode( GLFWvidmode *mode );
+
+/* Input handling */
+GLFWAPI void glfwPollEvents( void );
+GLFWAPI void glfwWaitEvents( void );
+GLFWAPI int glfwGetKey( int key );
+GLFWAPI int glfwGetMouseButton( int button );
+GLFWAPI void glfwGetMousePos( int *xpos, int *ypos );
+GLFWAPI void glfwSetMousePos( int xpos, int ypos );
+GLFWAPI int glfwGetMouseWheel( void );
+GLFWAPI void glfwSetMouseWheel( int pos );
+GLFWAPI void glfwSetKeyCallback( GLFWkeyfun cbfun );
+GLFWAPI void glfwSetCharCallback( GLFWcharfun cbfun );
+GLFWAPI void glfwSetMouseButtonCallback( GLFWmousebuttonfun cbfun );
+GLFWAPI void glfwSetMousePosCallback( GLFWmouseposfun cbfun );
+GLFWAPI void glfwSetMouseWheelCallback( GLFWmousewheelfun cbfun );
+
+/* Joystick input */
+GLFWAPI int glfwGetJoystickParam( int joy, int param );
+GLFWAPI int glfwGetJoystickPos( int joy, float *pos, int numaxes );
+GLFWAPI int glfwGetJoystickButtons( int joy, unsigned char *buttons, int numbuttons );
+
+/* Time */
+GLFWAPI double glfwGetTime( void );
+GLFWAPI void glfwSetTime( double time );
+
+/* Extension support */
+GLFWAPI int glfwExtensionSupported( const char *extension );
+GLFWAPI void* glfwGetProcAddress( const char *procname );
+GLFWAPI void glfwGetGLVersion( int *major, int *minor, int *rev );
+
+/* Enable/disable functions */
+GLFWAPI void glfwEnable( int token );
+GLFWAPI void glfwDisable( int token );
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __glfw_h_ */
+
diff --git a/lib/carbon/CMakeLists.txt b/lib/carbon/CMakeLists.txt
new file mode 100644
index 00000000..51c98545
--- /dev/null
+++ b/lib/carbon/CMakeLists.txt
@@ -0,0 +1,38 @@
+
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/libglfw.pc.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/libglfw.pc @ONLY)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/lib
+ ${GLFW_INCLUDE_DIR})
+
+set(libglfw_SOURCES
+ ${common_SOURCES}
+ carbon_enable.c
+ carbon_fullscreen.c
+ carbon_glext.c
+ carbon_init.c
+ carbon_joystick.c
+ carbon_time.c
+ carbon_window.c)
+
+add_library(libglfwStatic STATIC ${libglfw_SOURCES})
+add_library(libglfwShared SHARED ${libglfw_SOURCES})
+target_link_libraries(libglfwShared ${GLFW_LIBRARIES})
+set_target_properties(libglfwStatic libglfwShared PROPERTIES
+ CLEAN_DIRECT_OUTPUT 1
+ OUTPUT_NAME glfw
+)
+
+# Append -fno-common to the compile flags to work around a bug in the Apple GCC
+get_target_property(CFLAGS libglfwShared COMPILE_FLAGS)
+if(NOT CFLAGS)
+ set(CFLAGS "")
+endif(NOT CFLAGS)
+set_target_properties(libglfwShared PROPERTIES COMPILE_FLAGS "${CFLAGS} -fno-common")
+
+install(TARGETS libglfwStatic libglfwShared DESTINATION lib)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libglfw.pc DESTINATION lib/pkgconfig)
+
diff --git a/lib/carbon/carbon_enable.c b/lib/carbon/carbon_enable.c
new file mode 100644
index 00000000..76b18fef
--- /dev/null
+++ b/lib/carbon/carbon_enable.c
@@ -0,0 +1,43 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Carbon/AGL/CGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003 Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund
+//
+// 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.
+//
+//========================================================================
+
+void _glfwPlatformEnableSystemKeys( void )
+{
+ // Nothing to do; event handling code checks the status of
+ // _glfwWin.sysKeysDisabled to ensure this behavior.
+}
+
+void _glfwPlatformDisableSystemKeys( void )
+{
+ // Nothing to do; event handling code checks the status of
+ // _glfwWin.sysKeysDisabled to ensure this behavior.
+}
+
diff --git a/lib/carbon/carbon_fullscreen.c b/lib/carbon/carbon_fullscreen.c
new file mode 100644
index 00000000..2fd54570
--- /dev/null
+++ b/lib/carbon/carbon_fullscreen.c
@@ -0,0 +1,127 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Carbon/AGL/CGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003 Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund
+//
+// 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"
+
+//========================================================================
+// _glfwVideoModesEqual() - Compares two video modes
+//========================================================================
+
+static int _glfwVideoModesEqual( GLFWvidmode* first,
+ GLFWvidmode* second )
+{
+ if( first->Width != second->Width )
+ return 0;
+
+ if( first->Height != second->Height )
+ return 0;
+
+ if( first->RedBits + first->GreenBits + first->BlueBits !=
+ second->RedBits + second->GreenBits + second->BlueBits )
+ return 0;
+
+ return 1;
+}
+
+//========================================================================
+// _glfwCGToGLFWVideoMode() - Converts a CG mode to a GLFW mode
+//========================================================================
+
+static void _glfwCGToGLFWVideoMode( CFDictionaryRef cgMode,
+ GLFWvidmode* glfwMode )
+{
+ int bitsPerSample;
+
+ CFNumberGetValue( CFDictionaryGetValue( cgMode, kCGDisplayWidth ),
+ kCFNumberIntType,
+ &(glfwMode->Width) );
+ CFNumberGetValue( CFDictionaryGetValue( cgMode, kCGDisplayHeight ),
+ kCFNumberIntType,
+ &(glfwMode->Height) );
+
+ CFNumberGetValue( CFDictionaryGetValue( cgMode, kCGDisplayBitsPerSample ),
+ kCFNumberIntType,
+ &bitsPerSample );
+
+ glfwMode->RedBits = bitsPerSample;
+ glfwMode->GreenBits = bitsPerSample;
+ glfwMode->BlueBits = bitsPerSample;
+}
+
+//========================================================================
+// _glfwPlatformGetVideoModes() - Get a list of available video modes
+//========================================================================
+
+int _glfwPlatformGetVideoModes( GLFWvidmode *list, int maxcount )
+{
+ int i, j, maxModes, numModes;
+ GLFWvidmode mode;
+ CFArrayRef availableModes = CGDisplayAvailableModes( kCGDirectMainDisplay );
+ CFIndex numberOfAvailableModes = CFArrayGetCount( availableModes );
+
+ numModes = 0;
+ maxModes = ( numberOfAvailableModes < maxcount ?
+ numberOfAvailableModes :
+ maxcount );
+
+ for( i = 0; i < maxModes; ++i )
+ {
+ _glfwCGToGLFWVideoMode( CFArrayGetValueAtIndex( availableModes, i ),
+ &mode );
+
+ // Is it a valid mode? (only list depths >= 15 bpp)
+ if( mode.RedBits + mode.GreenBits + mode.BlueBits < 15 )
+ continue;
+
+ // Check for duplicate of current mode in target list
+ for( j = 0; j < numModes; ++j )
+ {
+ if( _glfwVideoModesEqual( &mode, &(list[j]) ) )
+ break;
+ }
+
+ // If empty list or no match found
+ if( numModes == 0 || j == numModes )
+ list[numModes++] = mode;
+ }
+
+ return numModes;
+}
+
+//========================================================================
+// glfwGetDesktopMode() - Get the desktop video mode
+//========================================================================
+
+void _glfwPlatformGetDesktopMode( GLFWvidmode *mode )
+{
+ _glfwCGToGLFWVideoMode( _glfwDesktopVideoMode, mode );
+}
+
diff --git a/lib/carbon/carbon_glext.c b/lib/carbon/carbon_glext.c
new file mode 100644
index 00000000..2a1018fc
--- /dev/null
+++ b/lib/carbon/carbon_glext.c
@@ -0,0 +1,53 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Carbon/AGL/CGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003 Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund
+//
+// 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"
+
+int _glfwPlatformExtensionSupported( const char *extension )
+{
+ // There are no AGL, CGL or NSGL extensions.
+ return GL_FALSE;
+}
+
+void * _glfwPlatformGetProcAddress( const char *procname )
+{
+ CFStringRef symbolName = CFStringCreateWithCString( kCFAllocatorDefault,
+ procname,
+ kCFStringEncodingASCII );
+
+ void *symbol = CFBundleGetFunctionPointerForName( _glfwLibrary.Libs.OpenGLFramework,
+ symbolName );
+
+ CFRelease( symbolName );
+
+ return symbol;
+}
+
diff --git a/lib/carbon/carbon_init.c b/lib/carbon/carbon_init.c
new file mode 100644
index 00000000..6a6d09ad
--- /dev/null
+++ b/lib/carbon/carbon_init.c
@@ -0,0 +1,159 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Carbon/AGL/CGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003 Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund
+// Copyright (c) 2006-2007 Robin Leffmann
+//
+// 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
+
+//========================================================================
+// Global variables
+//========================================================================
+
+// KCHR resource pointer for keycode translation
+void *KCHRPtr;
+
+
+//========================================================================
+// Terminate GLFW when exiting application
+//========================================================================
+
+static void glfw_atexit( void )
+{
+ glfwTerminate();
+}
+
+
+#define NO_BUNDLE_MESSAGE \
+ "Working in unbundled mode. " \
+ "You should build a .app wrapper for your Mac OS X applications.\n"
+
+#define UNBUNDLED \
+ fprintf(stderr, NO_BUNDLE_MESSAGE); \
+ _glfwLibrary.Unbundled = 1; \
+ return
+
+void _glfwChangeToResourcesDirectory( void )
+{
+ CFBundleRef mainBundle = CFBundleGetMainBundle();
+ if( mainBundle == NULL )
+ {
+ UNBUNDLED;
+ }
+
+ CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL( mainBundle );
+ char resourcesPath[ _GLFW_MAX_PATH_LENGTH ];
+
+ CFStringRef lastComponent = CFURLCopyLastPathComponent( resourcesURL );
+ if( kCFCompareEqualTo != CFStringCompare(
+ CFSTR( "Resources" ),
+ lastComponent,
+ 0 ) )
+ {
+ UNBUNDLED;
+ }
+
+ CFRelease( lastComponent );
+
+ if( !CFURLGetFileSystemRepresentation( resourcesURL,
+ TRUE,
+ (UInt8*)resourcesPath,
+ _GLFW_MAX_PATH_LENGTH ) )
+ {
+ CFRelease( resourcesURL );
+ UNBUNDLED;
+ }
+
+ CFRelease( resourcesURL );
+
+ if( chdir( resourcesPath ) != 0 )
+ {
+ UNBUNDLED;
+ }
+}
+
+int _glfwPlatformInit( void )
+{
+ struct timeval tv;
+ UInt32 nullDummy = 0;
+
+ _glfwWin.window = NULL;
+ _glfwWin.aglContext = NULL;
+ _glfwWin.cglContext = NULL;
+ _glfwWin.windowUPP = NULL;
+
+ _glfwInput.Modifiers = 0;
+
+ _glfwLibrary.Unbundled = 0;
+
+ _glfwLibrary.Libs.OpenGLFramework =
+ CFBundleGetBundleWithIdentifier( CFSTR( "com.apple.opengl" ) );
+ if( _glfwLibrary.Libs.OpenGLFramework == NULL )
+ {
+ fprintf( stderr, "glfwInit failing because you aren't linked to OpenGL\n" );
+ return GL_FALSE;
+ }
+
+ _glfwDesktopVideoMode = CGDisplayCurrentMode( kCGDirectMainDisplay );
+ if( _glfwDesktopVideoMode == NULL )
+ {
+ fprintf( stderr, "glfwInit failing because it kind find the desktop display mode\n" );
+ return GL_FALSE;
+ }
+
+ // Install atexit routine
+ atexit( glfw_atexit );
+
+ _glfwChangeToResourcesDirectory();
+
+ // Ugly hack to reduce the nasty jump that occurs at the first non-
+ // sys keypress, caused by OS X loading certain meta scripts used
+ // for lexical- and raw keycode translation - instead of letting
+ // this happen while our application is running, we do some blunt
+ // function calls in advance just to get the script caching out of
+ // the way BEFORE our window/screen is opened. These calls might
+ // generate err return codes, but we don't care in this case.
+ // NOTE: KCHRPtr is declared globally, because we need it later on.
+ KCHRPtr = (void *)GetScriptVariable( smCurrentScript, smKCHRCache );
+ KeyTranslate( KCHRPtr, 0, &nullDummy );
+ UppercaseText( (char *)&nullDummy, 0, smSystemScript );
+
+ gettimeofday( &tv, NULL );
+ _glfwLibrary.Timer.t0 = tv.tv_sec + (double) tv.tv_usec / 1000000.0;
+
+ return GL_TRUE;
+}
+
+int _glfwPlatformTerminate( void )
+{
+ return GL_TRUE;
+}
+
diff --git a/lib/carbon/carbon_joystick.c b/lib/carbon/carbon_joystick.c
new file mode 100644
index 00000000..3cf47ac5
--- /dev/null
+++ b/lib/carbon/carbon_joystick.c
@@ -0,0 +1,51 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Carbon/AGL/CGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003 Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund
+//
+// 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"
+
+// TO DO: use HID manager to implement joystick support.
+
+int _glfwPlatformGetJoystickParam( int joy, int param )
+{
+ // GL_FALSE == 0
+ return 0;
+}
+
+int _glfwPlatformGetJoystickPos( int joy, float *pos, int numaxes )
+{
+ return 0;
+}
+
+int _glfwPlatformGetJoystickButtons( int joy, unsigned char *buttons, int numbuttons )
+{
+ return 0;
+}
+
diff --git a/lib/carbon/carbon_time.c b/lib/carbon/carbon_time.c
new file mode 100644
index 00000000..64de6d70
--- /dev/null
+++ b/lib/carbon/carbon_time.c
@@ -0,0 +1,62 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Carbon/AGL/CGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003 Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund
+//
+// 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"
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Return timer value in seconds
+//========================================================================
+
+double _glfwPlatformGetTime( void )
+{
+ struct timeval tv;
+
+ gettimeofday( &tv, NULL );
+ return tv.tv_sec + (double) tv.tv_usec / 1000000.0 - _glfwLibrary.Timer.t0;
+}
+
+
+//========================================================================
+// Set timer value in seconds
+//========================================================================
+
+void _glfwPlatformSetTime( double time )
+{
+ struct timeval tv;
+
+ gettimeofday( &tv, NULL );
+ _glfwLibrary.Timer.t0 = tv.tv_sec + (double) tv.tv_usec / 1000000.0 - time;
+}
+
diff --git a/lib/carbon/carbon_window.c b/lib/carbon/carbon_window.c
new file mode 100644
index 00000000..4c709ede
--- /dev/null
+++ b/lib/carbon/carbon_window.c
@@ -0,0 +1,1309 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Carbon/AGL/CGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003 Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund
+// Copyright (c) 2006-2007 Robin Leffmann
+//
+// 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"
+
+#define _glfwTestModifier( modifierMask, glfwKey ) \
+if ( changed & modifierMask ) \
+{ \
+ _glfwInputKey( glfwKey, (modifiers & modifierMask ? GLFW_PRESS : GLFW_RELEASE) ); \
+}
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+static void handleMacModifierChange( UInt32 modifiers )
+{
+ UInt32 changed = modifiers ^ _glfwInput.Modifiers;
+
+ // The right *key variants below never actually occur
+ // There also isn't even a broken right command key constant
+ _glfwTestModifier( shiftKey, GLFW_KEY_LSHIFT );
+ _glfwTestModifier( rightShiftKey, GLFW_KEY_RSHIFT );
+ _glfwTestModifier( controlKey, GLFW_KEY_LCTRL );
+ _glfwTestModifier( rightControlKey, GLFW_KEY_RCTRL );
+ _glfwTestModifier( optionKey, GLFW_KEY_LALT );
+ _glfwTestModifier( rightOptionKey, GLFW_KEY_RALT );
+ _glfwTestModifier( cmdKey, GLFW_KEY_LSUPER );
+
+ _glfwInput.Modifiers = modifiers;
+}
+
+static void handleMacKeyChange( UInt32 keyCode, int action )
+{
+ switch ( keyCode )
+ {
+ case MAC_KEY_ENTER: _glfwInputKey( GLFW_KEY_ENTER, action); break;
+ case MAC_KEY_RETURN: _glfwInputKey( GLFW_KEY_KP_ENTER, action); break;
+ case MAC_KEY_ESC: _glfwInputKey( GLFW_KEY_ESC, action); break;
+ case MAC_KEY_F1: _glfwInputKey( GLFW_KEY_F1, action); break;
+ case MAC_KEY_F2: _glfwInputKey( GLFW_KEY_F2, action); break;
+ case MAC_KEY_F3: _glfwInputKey( GLFW_KEY_F3, action); break;
+ case MAC_KEY_F4: _glfwInputKey( GLFW_KEY_F4, action); break;
+ case MAC_KEY_F5: _glfwInputKey( GLFW_KEY_F5, action); break;
+ case MAC_KEY_F6: _glfwInputKey( GLFW_KEY_F6, action); break;
+ case MAC_KEY_F7: _glfwInputKey( GLFW_KEY_F7, action); break;
+ case MAC_KEY_F8: _glfwInputKey( GLFW_KEY_F8, action); break;
+ case MAC_KEY_F9: _glfwInputKey( GLFW_KEY_F9, action); break;
+ case MAC_KEY_F10: _glfwInputKey( GLFW_KEY_F10, action); break;
+ case MAC_KEY_F11: _glfwInputKey( GLFW_KEY_F11, action); break;
+ case MAC_KEY_F12: _glfwInputKey( GLFW_KEY_F12, action); break;
+ case MAC_KEY_F13: _glfwInputKey( GLFW_KEY_F13, action); break;
+ case MAC_KEY_F14: _glfwInputKey( GLFW_KEY_F14, action); break;
+ case MAC_KEY_F15: _glfwInputKey( GLFW_KEY_F15, action); break;
+ case MAC_KEY_UP: _glfwInputKey( GLFW_KEY_UP, action); break;
+ case MAC_KEY_DOWN: _glfwInputKey( GLFW_KEY_DOWN, action); break;
+ case MAC_KEY_LEFT: _glfwInputKey( GLFW_KEY_LEFT, action); break;
+ case MAC_KEY_RIGHT: _glfwInputKey( GLFW_KEY_RIGHT, action); break;
+ case MAC_KEY_TAB: _glfwInputKey( GLFW_KEY_TAB, action); break;
+ case MAC_KEY_BACKSPACE: _glfwInputKey( GLFW_KEY_BACKSPACE, action); break;
+ case MAC_KEY_HELP: _glfwInputKey( GLFW_KEY_INSERT, action); break;
+ case MAC_KEY_DEL: _glfwInputKey( GLFW_KEY_DEL, action); break;
+ case MAC_KEY_PAGEUP: _glfwInputKey( GLFW_KEY_PAGEUP, action); break;
+ case MAC_KEY_PAGEDOWN: _glfwInputKey( GLFW_KEY_PAGEDOWN, action); break;
+ case MAC_KEY_HOME: _glfwInputKey( GLFW_KEY_HOME, action); break;
+ case MAC_KEY_END: _glfwInputKey( GLFW_KEY_END, action); break;
+ case MAC_KEY_KP_0: _glfwInputKey( GLFW_KEY_KP_0, action); break;
+ case MAC_KEY_KP_1: _glfwInputKey( GLFW_KEY_KP_1, action); break;
+ case MAC_KEY_KP_2: _glfwInputKey( GLFW_KEY_KP_2, action); break;
+ case MAC_KEY_KP_3: _glfwInputKey( GLFW_KEY_KP_3, action); break;
+ case MAC_KEY_KP_4: _glfwInputKey( GLFW_KEY_KP_4, action); break;
+ case MAC_KEY_KP_5: _glfwInputKey( GLFW_KEY_KP_5, action); break;
+ case MAC_KEY_KP_6: _glfwInputKey( GLFW_KEY_KP_6, action); break;
+ case MAC_KEY_KP_7: _glfwInputKey( GLFW_KEY_KP_7, action); break;
+ case MAC_KEY_KP_8: _glfwInputKey( GLFW_KEY_KP_8, action); break;
+ case MAC_KEY_KP_9: _glfwInputKey( GLFW_KEY_KP_9, action); break;
+ case MAC_KEY_KP_DIVIDE: _glfwInputKey( GLFW_KEY_KP_DIVIDE, action); break;
+ case MAC_KEY_KP_MULTIPLY: _glfwInputKey( GLFW_KEY_KP_MULTIPLY, action); break;
+ case MAC_KEY_KP_SUBTRACT: _glfwInputKey( GLFW_KEY_KP_SUBTRACT, action); break;
+ case MAC_KEY_KP_ADD: _glfwInputKey( GLFW_KEY_KP_ADD, action); break;
+ case MAC_KEY_KP_DECIMAL: _glfwInputKey( GLFW_KEY_KP_DECIMAL, action); break;
+ case MAC_KEY_KP_EQUAL: _glfwInputKey( GLFW_KEY_KP_EQUAL, action); break;
+ case MAC_KEY_KP_ENTER: _glfwInputKey( GLFW_KEY_KP_ENTER, action); break;
+ case MAC_KEY_NUMLOCK: _glfwInputKey( GLFW_KEY_KP_NUM_LOCK, action); break;
+ default:
+ {
+ extern void *KCHRPtr;
+ UInt32 state = 0;
+ char charCode = (char)KeyTranslate( KCHRPtr, keyCode, &state );
+ UppercaseText( &charCode, 1, smSystemScript );
+ _glfwInputKey( (unsigned char)charCode, action );
+ }
+ break;
+ }
+}
+
+// The set of event class/kind combinations supported by keyEventHandler
+// This is used by installEventHandlers below
+static const EventTypeSpec GLFW_KEY_EVENT_TYPES[] =
+{
+ { kEventClassKeyboard, kEventRawKeyDown },
+ { kEventClassKeyboard, kEventRawKeyUp },
+ { kEventClassKeyboard, kEventRawKeyRepeat },
+ { kEventClassKeyboard, kEventRawKeyModifiersChanged }
+};
+
+static OSStatus keyEventHandler( EventHandlerCallRef handlerCallRef,
+ EventRef event,
+ void *userData )
+{
+ UInt32 keyCode;
+ short int keyChar;
+ UInt32 modifiers;
+
+ switch( GetEventKind( event ) )
+ {
+ case kEventRawKeyRepeat:
+ case kEventRawKeyDown:
+ {
+ if( GetEventParameter( event,
+ kEventParamKeyCode,
+ typeUInt32,
+ NULL,
+ sizeof( UInt32 ),
+ NULL,
+ &keyCode ) == noErr )
+ {
+ handleMacKeyChange( keyCode, GLFW_PRESS );
+ }
+ if( GetEventParameter( event,
+ kEventParamKeyUnicodes,
+ typeUnicodeText,
+ NULL,
+ sizeof(keyChar),
+ NULL,
+ &keyChar) == noErr )
+ {
+ _glfwInputChar( keyChar, GLFW_PRESS );
+ }
+ return noErr;
+ }
+
+ case kEventRawKeyUp:
+ {
+ if( GetEventParameter( event,
+ kEventParamKeyCode,
+ typeUInt32,
+ NULL,
+ sizeof( UInt32 ),
+ NULL,
+ &keyCode ) == noErr )
+ {
+ handleMacKeyChange( keyCode, GLFW_RELEASE );
+ }
+ if( GetEventParameter( event,
+ kEventParamKeyUnicodes,
+ typeUnicodeText,
+ NULL,
+ sizeof(keyChar),
+ NULL,
+ &keyChar) == noErr )
+ {
+ _glfwInputChar( keyChar, GLFW_RELEASE );
+ }
+ return noErr;
+ }
+
+ case kEventRawKeyModifiersChanged:
+ {
+ if( GetEventParameter( event,
+ kEventParamKeyModifiers,
+ typeUInt32,
+ NULL,
+ sizeof( UInt32 ),
+ NULL,
+ &modifiers ) == noErr )
+ {
+ handleMacModifierChange( modifiers );
+ return noErr;
+ }
+ }
+ break;
+ }
+
+ return eventNotHandledErr;
+}
+
+// The set of event class/kind combinations supported by mouseEventHandler
+// This is used by installEventHandlers below
+static const EventTypeSpec GLFW_MOUSE_EVENT_TYPES[] =
+{
+ { kEventClassMouse, kEventMouseDown },
+ { kEventClassMouse, kEventMouseUp },
+ { kEventClassMouse, kEventMouseMoved },
+ { kEventClassMouse, kEventMouseDragged },
+ { kEventClassMouse, kEventMouseWheelMoved },
+};
+
+static OSStatus mouseEventHandler( EventHandlerCallRef handlerCallRef,
+ EventRef event,
+ void *userData )
+{
+ switch( GetEventKind( event ) )
+ {
+ case kEventMouseDown:
+ {
+ WindowRef window;
+ EventRecord oldStyleMacEvent;
+ ConvertEventRefToEventRecord( event, &oldStyleMacEvent );
+ if( FindWindow ( oldStyleMacEvent.where, &window ) == inMenuBar )
+ {
+ MenuSelect( oldStyleMacEvent.where );
+ HiliteMenu(0);
+ return noErr;
+ }
+ else
+ {
+ EventMouseButton button;
+ if( GetEventParameter( event,
+ kEventParamMouseButton,
+ typeMouseButton,
+ NULL,
+ sizeof( EventMouseButton ),
+ NULL,
+ &button ) == noErr )
+ {
+ button -= kEventMouseButtonPrimary;
+ if( button <= GLFW_MOUSE_BUTTON_LAST )
+ {
+ _glfwInputMouseClick( button + GLFW_MOUSE_BUTTON_LEFT,
+ GLFW_PRESS );
+ }
+ return noErr;
+ }
+ }
+ break;
+ }
+
+ case kEventMouseUp:
+ {
+ EventMouseButton button;
+ if( GetEventParameter( event,
+ kEventParamMouseButton,
+ typeMouseButton,
+ NULL,
+ sizeof( EventMouseButton ),
+ NULL,
+ &button ) == noErr )
+ {
+ button -= kEventMouseButtonPrimary;
+ if( button <= GLFW_MOUSE_BUTTON_LAST )
+ {
+ _glfwInputMouseClick( button + GLFW_MOUSE_BUTTON_LEFT,
+ GLFW_RELEASE );
+ }
+ return noErr;
+ }
+ break;
+ }
+
+ case kEventMouseMoved:
+ case kEventMouseDragged:
+ {
+ HIPoint mouseLocation;
+ if( _glfwWin.mouseLock )
+ {
+ if( GetEventParameter( event,
+ kEventParamMouseDelta,
+ typeHIPoint,
+ NULL,
+ sizeof( HIPoint ),
+ NULL,
+ &mouseLocation ) != noErr )
+ {
+ break;
+ }
+
+ _glfwInput.MousePosX += mouseLocation.x;
+ _glfwInput.MousePosY += mouseLocation.y;
+ }
+ else
+ {
+ if( GetEventParameter( event,
+ kEventParamMouseLocation,
+ typeHIPoint,
+ NULL,
+ sizeof( HIPoint ),
+ NULL,
+ &mouseLocation ) != noErr )
+ {
+ break;
+ }
+
+ _glfwInput.MousePosX = mouseLocation.x;
+ _glfwInput.MousePosY = mouseLocation.y;
+
+ if( !_glfwWin.fullscreen )
+ {
+ Rect content;
+ GetWindowBounds( _glfwWin.window,
+ kWindowContentRgn,
+ &content );
+
+ _glfwInput.MousePosX -= content.left;
+ _glfwInput.MousePosY -= content.top;
+ }
+ }
+
+ if( _glfwWin.mousePosCallback )
+ {
+ _glfwWin.mousePosCallback( _glfwInput.MousePosX,
+ _glfwInput.MousePosY );
+ }
+
+ break;
+ }
+
+ case kEventMouseWheelMoved:
+ {
+ EventMouseWheelAxis axis;
+ if( GetEventParameter( event,
+ kEventParamMouseWheelAxis,
+ typeMouseWheelAxis,
+ NULL,
+ sizeof( EventMouseWheelAxis ),
+ NULL,
+ &axis) == noErr )
+ {
+ long wheelDelta;
+ if( axis == kEventMouseWheelAxisY &&
+ GetEventParameter( event,
+ kEventParamMouseWheelDelta,
+ typeLongInteger,
+ NULL,
+ sizeof( long ),
+ NULL,
+ &wheelDelta ) == noErr )
+ {
+ _glfwInput.WheelPos += wheelDelta;
+ if( _glfwWin.mouseWheelCallback )
+ {
+ _glfwWin.mouseWheelCallback( _glfwInput.WheelPos );
+ }
+ return noErr;
+ }
+ }
+ break;
+ }
+ }
+
+ return eventNotHandledErr;
+}
+
+// The set of event class/kind combinations supported by commandHandler
+// This is used by installEventHandlers below
+static const EventTypeSpec GLFW_COMMAND_EVENT_TYPES[] =
+{
+ { kEventClassCommand, kEventCommandProcess }
+};
+
+static OSStatus commandHandler( EventHandlerCallRef handlerCallRef,
+ EventRef event,
+ void *userData )
+{
+ if( _glfwWin.sysKeysDisabled )
+ {
+ // TODO: Give adequate UI feedback that this is the case
+ return eventNotHandledErr;
+ }
+
+ HICommand command;
+ if( GetEventParameter( event,
+ kEventParamDirectObject,
+ typeHICommand,
+ NULL,
+ sizeof( HICommand ),
+ NULL,
+ &command ) == noErr )
+ {
+ switch( command.commandID )
+ {
+ case kHICommandClose:
+ case kHICommandQuit:
+ {
+ // Check if the program wants us to close the window
+ if( _glfwWin.windowCloseCallback )
+ {
+ if( _glfwWin.windowCloseCallback() )
+ {
+ glfwCloseWindow();
+ }
+ }
+ else
+ {
+ glfwCloseWindow();
+ }
+ return noErr;
+ }
+ }
+ }
+
+ return eventNotHandledErr;
+}
+
+// The set of event class/kind combinations supported by windowEventHandler
+// This is used by installEventHandlers below
+static const EventTypeSpec GLFW_WINDOW_EVENT_TYPES[] =
+{
+ { kEventClassWindow, kEventWindowBoundsChanged },
+ { kEventClassWindow, kEventWindowClose },
+ { kEventClassWindow, kEventWindowDrawContent },
+ { kEventClassWindow, kEventWindowActivated },
+ { kEventClassWindow, kEventWindowDeactivated },
+};
+
+static OSStatus windowEventHandler( EventHandlerCallRef handlerCallRef,
+ EventRef event,
+ void *userData )
+{
+ switch( GetEventKind(event) )
+ {
+ case kEventWindowBoundsChanged:
+ {
+ WindowRef window;
+ GetEventParameter( event,
+ kEventParamDirectObject,
+ typeWindowRef,
+ NULL,
+ sizeof(WindowRef),
+ NULL,
+ &window );
+
+ Rect rect;
+ GetWindowPortBounds( window, &rect );
+
+ if( _glfwWin.width != rect.right ||
+ _glfwWin.height != rect.bottom )
+ {
+ aglUpdateContext( _glfwWin.aglContext );
+
+ _glfwWin.width = rect.right;
+ _glfwWin.height = rect.bottom;
+ if( _glfwWin.windowSizeCallback )
+ {
+ _glfwWin.windowSizeCallback( _glfwWin.width, _glfwWin.height );
+ }
+ // Emulate (force) content invalidation
+ if( _glfwWin.windowRefreshCallback )
+ {
+ _glfwWin.windowRefreshCallback();
+ }
+ }
+ break;
+ }
+
+ case kEventWindowClose:
+ {
+ // Check if the client wants us to close the window
+ if( _glfwWin.windowCloseCallback )
+ {
+ if( _glfwWin.windowCloseCallback() )
+ {
+ glfwCloseWindow();
+ }
+ }
+ else
+ {
+ glfwCloseWindow();
+ }
+ return noErr;
+ }
+
+ case kEventWindowDrawContent:
+ {
+ if( _glfwWin.windowRefreshCallback )
+ {
+ _glfwWin.windowRefreshCallback();
+ }
+ break;
+ }
+
+ case kEventWindowActivated:
+ {
+ _glfwWin.active = GL_TRUE;
+ break;
+ }
+
+ case kEventWindowDeactivated:
+ {
+ _glfwWin.active = GL_FALSE;
+ _glfwInputDeactivation();
+ break;
+ }
+ }
+
+ return eventNotHandledErr;
+}
+
+static int installEventHandlers( void )
+{
+ OSStatus error;
+
+ _glfwWin.mouseUPP = NewEventHandlerUPP( mouseEventHandler );
+
+ error = InstallEventHandler( GetApplicationEventTarget(),
+ _glfwWin.mouseUPP,
+ GetEventTypeCount( GLFW_MOUSE_EVENT_TYPES ),
+ GLFW_MOUSE_EVENT_TYPES,
+ NULL,
+ NULL );
+ if( error != noErr )
+ {
+ fprintf( stderr, "Failed to install Carbon application mouse event handler\n" );
+ return GL_FALSE;
+ }
+
+ _glfwWin.commandUPP = NewEventHandlerUPP( commandHandler );
+
+ error = InstallEventHandler( GetApplicationEventTarget(),
+ _glfwWin.commandUPP,
+ GetEventTypeCount( GLFW_COMMAND_EVENT_TYPES ),
+ GLFW_COMMAND_EVENT_TYPES,
+ NULL,
+ NULL );
+ if( error != noErr )
+ {
+ fprintf( stderr, "Failed to install Carbon application command event handler\n" );
+ return GL_FALSE;
+ }
+
+ _glfwWin.keyboardUPP = NewEventHandlerUPP( keyEventHandler );
+
+ error = InstallEventHandler( GetApplicationEventTarget(),
+ _glfwWin.keyboardUPP,
+ GetEventTypeCount( GLFW_KEY_EVENT_TYPES ),
+ GLFW_KEY_EVENT_TYPES,
+ NULL,
+ NULL );
+ if( error != noErr )
+ {
+ fprintf( stderr, "Failed to install Carbon application key event handler\n" );
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+#define _setAGLAttribute( aglAttributeName, AGLparameter ) \
+if ( AGLparameter != 0 ) \
+{ \
+ AGLpixelFormatAttributes[numAGLAttrs++] = aglAttributeName; \
+ AGLpixelFormatAttributes[numAGLAttrs++] = AGLparameter; \
+}
+
+#define _setCGLAttribute( cglAttributeName, CGLparameter ) \
+if ( CGLparameter != 0 ) \
+{ \
+ CGLpixelFormatAttributes[ numCGLAttrs++ ] = cglAttributeName; \
+ CGLpixelFormatAttributes[ numCGLAttrs++ ] = CGLparameter; \
+}
+
+//========================================================================
+// Here is where the window is created, and
+// the OpenGL rendering context is created
+//========================================================================
+
+int _glfwPlatformOpenWindow( int width, int height,
+ const _GLFWwndconfig *wndconfig,
+ const _GLFWfbconfig *fbconfig )
+{
+ OSStatus error;
+ unsigned int windowAttributes;
+ ProcessSerialNumber psn;
+
+ // TODO: Break up this function!
+
+ _glfwWin.windowUPP = NULL;
+ _glfwWin.mouseUPP = NULL;
+ _glfwWin.keyboardUPP = NULL;
+ _glfwWin.commandUPP = NULL;
+ _glfwWin.window = NULL;
+ _glfwWin.aglContext = NULL;
+ _glfwWin.aglPixelFormat = NULL;
+ _glfwWin.cglContext = NULL;
+ _glfwWin.cglPixelFormat = NULL;
+
+ _glfwWin.refreshRate = wndconfig->refreshRate;
+
+ // Fail if OpenGL 3.0 or above was requested
+ if( wndconfig->glMajor > 2 )
+ {
+ fprintf( stderr, "OpenGL 3.0+ is not yet supported on Mac OS X\n" );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ if( _glfwLibrary.Unbundled )
+ {
+ if( GetCurrentProcess( &psn ) != noErr )
+ {
+ fprintf( stderr, "Failed to get the process serial number\n" );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ if( TransformProcessType( &psn, kProcessTransformToForegroundApplication ) != noErr )
+ {
+ fprintf( stderr, "Failed to become a foreground application\n" );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ if( wndconfig->mode == GLFW_FULLSCREEN )
+ {
+ if( SetFrontProcess( &psn ) != noErr )
+ {
+ fprintf( stderr, "Failed to become the front process\n" );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+ }
+ }
+
+ if( !installEventHandlers() )
+ {
+ fprintf( stderr,
+ "Failed to install Carbon application event handlers\n" );
+
+ _glfwPlatformTerminate();
+ return GL_FALSE;
+ }
+
+ // Windowed or fullscreen; AGL or CGL? Quite the mess...
+ // AGL appears to be the only choice for attaching OpenGL contexts to
+ // Carbon windows, but it leaves the user no control over fullscreen
+ // mode stretching. Solution: AGL for windowed, CGL for fullscreen.
+ if( wndconfig->mode == GLFW_WINDOW )
+ {
+ // create AGL pixel format attribute list
+ GLint AGLpixelFormatAttributes[256];
+ int numAGLAttrs = 0;
+
+ AGLpixelFormatAttributes[numAGLAttrs++] = AGL_RGBA;
+ AGLpixelFormatAttributes[numAGLAttrs++] = AGL_DOUBLEBUFFER;
+ AGLpixelFormatAttributes[numAGLAttrs++] = AGL_CLOSEST_POLICY;
+
+ if( fbconfig->stereo )
+ {
+ AGLpixelFormatAttributes[numAGLAttrs++] = AGL_STEREO;
+ }
+
+ _setAGLAttribute( AGL_AUX_BUFFERS, fbconfig->auxBuffers);
+ _setAGLAttribute( AGL_RED_SIZE, fbconfig->redBits );
+ _setAGLAttribute( AGL_GREEN_SIZE, fbconfig->greenBits );
+ _setAGLAttribute( AGL_BLUE_SIZE, fbconfig->blueBits );
+ _setAGLAttribute( AGL_ALPHA_SIZE, fbconfig->alphaBits );
+ _setAGLAttribute( AGL_DEPTH_SIZE, fbconfig->depthBits );
+ _setAGLAttribute( AGL_STENCIL_SIZE, fbconfig->stencilBits );
+ _setAGLAttribute( AGL_ACCUM_RED_SIZE, fbconfig->accumRedBits );
+ _setAGLAttribute( AGL_ACCUM_GREEN_SIZE, fbconfig->accumGreenBits );
+ _setAGLAttribute( AGL_ACCUM_BLUE_SIZE, fbconfig->accumBlueBits );
+ _setAGLAttribute( AGL_ACCUM_ALPHA_SIZE, fbconfig->accumAlphaBits );
+
+ if( fbconfig->samples > 1 )
+ {
+ _setAGLAttribute( AGL_SAMPLE_BUFFERS_ARB, 1 );
+ _setAGLAttribute( AGL_SAMPLES_ARB, fbconfig->samples );
+ AGLpixelFormatAttributes[numAGLAttrs++] = AGL_NO_RECOVERY;
+ }
+
+ AGLpixelFormatAttributes[numAGLAttrs++] = AGL_NONE;
+
+ // create pixel format descriptor
+ AGLDevice mainMonitor = GetMainDevice();
+ _glfwWin.aglPixelFormat = aglChoosePixelFormat( &mainMonitor,
+ 1,
+ AGLpixelFormatAttributes );
+ if( _glfwWin.aglPixelFormat == NULL )
+ {
+ fprintf( stderr,
+ "Failed to choose AGL pixel format: %s\n",
+ aglErrorString( aglGetError() ) );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ // create AGL context
+ _glfwWin.aglContext = aglCreateContext( _glfwWin.aglPixelFormat, NULL );
+
+ if( _glfwWin.aglContext == NULL )
+ {
+ fprintf( stderr,
+ "Failed to create AGL context: %s\n",
+ aglErrorString( aglGetError() ) );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ // create window
+ Rect windowContentBounds;
+ windowContentBounds.left = 0;
+ windowContentBounds.top = 0;
+ windowContentBounds.right = width;
+ windowContentBounds.bottom = height;
+
+ windowAttributes = ( kWindowCloseBoxAttribute |
+ kWindowCollapseBoxAttribute |
+ kWindowStandardHandlerAttribute );
+
+ if( wndconfig->windowNoResize )
+ {
+ windowAttributes |= kWindowLiveResizeAttribute;
+ }
+ else
+ {
+ windowAttributes |= ( kWindowFullZoomAttribute |
+ kWindowResizableAttribute );
+ }
+
+ error = CreateNewWindow( kDocumentWindowClass,
+ windowAttributes,
+ &windowContentBounds,
+ &( _glfwWin.window ) );
+ if( ( error != noErr ) || ( _glfwWin.window == NULL ) )
+ {
+ fprintf( stderr, "Failed to create Carbon window\n" );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ _glfwWin.windowUPP = NewEventHandlerUPP( windowEventHandler );
+
+ error = InstallWindowEventHandler( _glfwWin.window,
+ _glfwWin.windowUPP,
+ GetEventTypeCount( GLFW_WINDOW_EVENT_TYPES ),
+ GLFW_WINDOW_EVENT_TYPES,
+ NULL,
+ NULL );
+ if( error != noErr )
+ {
+ fprintf( stderr, "Failed to install Carbon window event handler\n" );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ // Don't care if we fail here
+ (void)SetWindowTitleWithCFString( _glfwWin.window, CFSTR( "GLFW Window" ) );
+ (void)RepositionWindow( _glfwWin.window,
+ NULL,
+ kWindowCenterOnMainScreen );
+
+ if( !aglSetDrawable( _glfwWin.aglContext,
+ GetWindowPort( _glfwWin.window ) ) )
+ {
+ fprintf( stderr,
+ "Failed to set the AGL context as the Carbon window drawable: %s\n",
+ aglErrorString( aglGetError() ) );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ // Make OpenGL context current
+ if( !aglSetCurrentContext( _glfwWin.aglContext ) )
+ {
+ fprintf( stderr,
+ "Failed to make AGL context current: %s\n",
+ aglErrorString( aglGetError() ) );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ ShowWindow( _glfwWin.window );
+ }
+ else
+ {
+ CGDisplayErr cgErr;
+ CGLError cglErr;
+
+ CFDictionaryRef optimalMode;
+
+ GLint numCGLvs = 0;
+
+ CGLPixelFormatAttribute CGLpixelFormatAttributes[64];
+ int numCGLAttrs = 0;
+
+ // variables for enumerating color depths
+ GLint rgbColorDepth;
+
+ // CGL pixel format attributes
+ _setCGLAttribute( kCGLPFADisplayMask,
+ CGDisplayIDToOpenGLDisplayMask( kCGDirectMainDisplay ) );
+
+ if( fbconfig->stereo )
+ {
+ CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAStereo;
+ }
+
+ if( fbconfig->samples > 1 )
+ {
+ _setCGLAttribute( kCGLPFASamples, (CGLPixelFormatAttribute)fbconfig->samples );
+ _setCGLAttribute( kCGLPFASampleBuffers, (CGLPixelFormatAttribute)1 );
+ CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFANoRecovery;
+ }
+
+ CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAFullScreen;
+ CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFADoubleBuffer;
+ CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAAccelerated;
+ CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFANoRecovery;
+ CGLpixelFormatAttributes[ numCGLAttrs++ ] = kCGLPFAMinimumPolicy;
+
+ _setCGLAttribute( kCGLPFAAccumSize,
+ (CGLPixelFormatAttribute)( fbconfig->accumRedBits \
+ + fbconfig->accumGreenBits \
+ + fbconfig->accumBlueBits \
+ + fbconfig->accumAlphaBits ) );
+
+ _setCGLAttribute( kCGLPFAAlphaSize, (CGLPixelFormatAttribute)fbconfig->alphaBits );
+ _setCGLAttribute( kCGLPFADepthSize, (CGLPixelFormatAttribute)fbconfig->depthBits );
+ _setCGLAttribute( kCGLPFAStencilSize, (CGLPixelFormatAttribute)fbconfig->stencilBits );
+ _setCGLAttribute( kCGLPFAAuxBuffers, (CGLPixelFormatAttribute)fbconfig->auxBuffers );
+
+ CGLpixelFormatAttributes[ numCGLAttrs++ ] = (CGLPixelFormatAttribute)NULL;
+
+ // create a suitable pixel format with above attributes..
+ cglErr = CGLChoosePixelFormat( CGLpixelFormatAttributes,
+ &_glfwWin.cglPixelFormat,
+ &numCGLvs );
+ if( cglErr != kCGLNoError )
+ {
+ fprintf( stderr,
+ "Failed to choose CGL pixel format: %s\n",
+ CGLErrorString( cglErr ) );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ // ..and create a rendering context using that pixel format
+ cglErr = CGLCreateContext( _glfwWin.cglPixelFormat, NULL, &_glfwWin.cglContext );
+ if( cglErr != kCGLNoError )
+ {
+ fprintf( stderr,
+ "Failed to create CGL context: %s\n",
+ CGLErrorString( cglErr ) );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ // enumerate depth of RGB channels - unlike AGL, CGL works with
+ // a single parameter reflecting the full depth of the frame buffer
+ (void)CGLDescribePixelFormat( _glfwWin.cglPixelFormat,
+ 0,
+ kCGLPFAColorSize,
+ &rgbColorDepth );
+
+ // capture the display for our application
+ cgErr = CGCaptureAllDisplays();
+ if( cgErr != kCGErrorSuccess )
+ {
+ fprintf( stderr,
+ "Failed to capture Core Graphics displays\n");
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ // find closest matching NON-STRETCHED display mode..
+ optimalMode = CGDisplayBestModeForParametersAndRefreshRateWithProperty(
+ kCGDirectMainDisplay,
+ rgbColorDepth,
+ width,
+ height,
+ wndconfig->refreshRate,
+ NULL,
+ NULL );
+ if( optimalMode == NULL )
+ {
+ fprintf( stderr,
+ "Failed to retrieve Core Graphics display mode\n");
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ // ..and switch to that mode
+ cgErr = CGDisplaySwitchToMode( kCGDirectMainDisplay, optimalMode );
+ if( cgErr != kCGErrorSuccess )
+ {
+ fprintf( stderr,
+ "Failed to switch to Core Graphics display mode\n");
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ // switch to our OpenGL context, and bring it up fullscreen
+ cglErr = CGLSetCurrentContext( _glfwWin.cglContext );
+ if( cglErr != kCGLNoError )
+ {
+ fprintf( stderr,
+ "Failed to make CGL context current: %s\n",
+ CGLErrorString( cglErr ) );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ cglErr = CGLSetFullScreen( _glfwWin.cglContext );
+ if( cglErr != kCGLNoError )
+ {
+ fprintf( stderr,
+ "Failed to set CGL fullscreen mode: %s\n",
+ CGLErrorString( cglErr ) );
+
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+ }
+
+ return GL_TRUE;
+}
+
+//========================================================================
+// Properly kill the window/video display
+//========================================================================
+
+void _glfwPlatformCloseWindow( void )
+{
+ if( _glfwWin.mouseUPP != NULL )
+ {
+ DisposeEventHandlerUPP( _glfwWin.mouseUPP );
+ _glfwWin.mouseUPP = NULL;
+ }
+ if( _glfwWin.commandUPP != NULL )
+ {
+ DisposeEventHandlerUPP( _glfwWin.commandUPP );
+ _glfwWin.commandUPP = NULL;
+ }
+ if( _glfwWin.keyboardUPP != NULL )
+ {
+ DisposeEventHandlerUPP( _glfwWin.keyboardUPP );
+ _glfwWin.keyboardUPP = NULL;
+ }
+ if( _glfwWin.windowUPP != NULL )
+ {
+ DisposeEventHandlerUPP( _glfwWin.windowUPP );
+ _glfwWin.windowUPP = NULL;
+ }
+
+ if( _glfwWin.fullscreen )
+ {
+ if( _glfwWin.cglContext != NULL )
+ {
+ CGLSetCurrentContext( NULL );
+ CGLClearDrawable( _glfwWin.cglContext );
+ CGLDestroyContext( _glfwWin.cglContext );
+ CGReleaseAllDisplays();
+ _glfwWin.cglContext = NULL;
+ }
+
+ if( _glfwWin.cglPixelFormat != NULL )
+ {
+ CGLDestroyPixelFormat( _glfwWin.cglPixelFormat );
+ _glfwWin.cglPixelFormat = NULL;
+ }
+ }
+ else
+ {
+ if( _glfwWin.aglContext != NULL )
+ {
+ aglSetCurrentContext( NULL );
+ aglSetDrawable( _glfwWin.aglContext, NULL );
+ aglDestroyContext( _glfwWin.aglContext );
+ _glfwWin.aglContext = NULL;
+ }
+
+ if( _glfwWin.aglPixelFormat != NULL )
+ {
+ aglDestroyPixelFormat( _glfwWin.aglPixelFormat );
+ _glfwWin.aglPixelFormat = NULL;
+ }
+ }
+
+ if( _glfwWin.window != NULL )
+ {
+ ReleaseWindow( _glfwWin.window );
+ _glfwWin.window = NULL;
+ }
+}
+
+//========================================================================
+// Set the window title
+//========================================================================
+
+void _glfwPlatformSetWindowTitle( const char *title )
+{
+ CFStringRef windowTitle;
+
+ if( !_glfwWin.fullscreen )
+ {
+ windowTitle = CFStringCreateWithCString( kCFAllocatorDefault,
+ title,
+ kCFStringEncodingISOLatin1 );
+
+ (void)SetWindowTitleWithCFString( _glfwWin.window, windowTitle );
+
+ CFRelease( windowTitle );
+ }
+}
+
+//========================================================================
+// Set the window size
+//========================================================================
+
+void _glfwPlatformSetWindowSize( int width, int height )
+{
+ if( !_glfwWin.fullscreen )
+ {
+ SizeWindow( _glfwWin.window, width, height, TRUE );
+ }
+}
+
+//========================================================================
+// Set the window position
+//========================================================================
+
+void _glfwPlatformSetWindowPos( int x, int y )
+{
+ if( !_glfwWin.fullscreen )
+ {
+ MoveWindow( _glfwWin.window, x, y, FALSE );
+ }
+}
+
+//========================================================================
+// Window iconification
+//========================================================================
+
+void _glfwPlatformIconifyWindow( void )
+{
+ if( !_glfwWin.fullscreen )
+ {
+ (void)CollapseWindow( _glfwWin.window, TRUE );
+ }
+}
+
+//========================================================================
+// Window un-iconification
+//========================================================================
+
+void _glfwPlatformRestoreWindow( void )
+{
+ if( !_glfwWin.fullscreen )
+ {
+ (void)CollapseWindow( _glfwWin.window, FALSE );
+ }
+}
+
+//========================================================================
+// Swap buffers (double-buffering) and poll any new events
+//========================================================================
+
+void _glfwPlatformSwapBuffers( void )
+{
+ if( _glfwWin.fullscreen )
+ {
+ CGLFlushDrawable( _glfwWin.cglContext );
+ }
+ else
+ {
+ aglSwapBuffers( _glfwWin.aglContext );
+ }
+}
+
+//========================================================================
+// Set double buffering swap interval
+//========================================================================
+
+void _glfwPlatformSwapInterval( int interval )
+{
+ GLint AGLparameter = interval;
+
+ // CGL doesn't seem to like intervals other than 0 (vsync off) or 1 (vsync on)
+ long CGLparameter = ( interval ? 1 : 0 );
+
+ if( _glfwWin.fullscreen )
+ {
+ // Don't care if we fail here..
+ (void)CGLSetParameter( _glfwWin.cglContext,
+ kCGLCPSwapInterval,
+ (GLint*) &CGLparameter );
+ }
+ else
+ {
+ // ..or here
+ (void)aglSetInteger( _glfwWin.aglContext,
+ AGL_SWAP_INTERVAL,
+ &AGLparameter );
+ }
+}
+
+//========================================================================
+// Read back framebuffer parameters from the context
+//========================================================================
+
+#define _getAGLAttribute( aglAttributeName, variableName ) \
+{ \
+ GLint aglValue; \
+ (void)aglDescribePixelFormat( _glfwWin.aglPixelFormat, aglAttributeName, &aglValue ); \
+ variableName = aglValue; \
+}
+
+#define _getCGLAttribute( cglAttributeName, variableName ) \
+{ \
+ GLint cglValue; \
+ (void)CGLDescribePixelFormat( _glfwWin.cglPixelFormat, 0, cglAttributeName, &cglValue ); \
+ variableName = cglValue; \
+}
+
+void _glfwPlatformRefreshWindowParams( void )
+{
+ GLint rgbColorDepth;
+ GLint rgbaAccumDepth = 0;
+ GLint rgbChannelDepth = 0;
+
+ if( _glfwWin.fullscreen )
+ {
+ _getCGLAttribute( kCGLPFAAccelerated, _glfwWin.accelerated );
+ _getCGLAttribute( kCGLPFAAlphaSize, _glfwWin.alphaBits );
+ _getCGLAttribute( kCGLPFADepthSize, _glfwWin.depthBits );
+ _getCGLAttribute( kCGLPFAStencilSize, _glfwWin.stencilBits );
+ _getCGLAttribute( kCGLPFAAuxBuffers, _glfwWin.auxBuffers );
+ _getCGLAttribute( kCGLPFAStereo, _glfwWin.stereo );
+ _getCGLAttribute( kCGLPFASamples, _glfwWin.samples );
+
+ // Enumerate depth of RGB channels - unlike AGL, CGL works with
+ // a single parameter reflecting the full depth of the frame buffer
+ (void)CGLDescribePixelFormat( _glfwWin.cglPixelFormat,
+ 0,
+ kCGLPFAColorSize,
+ &rgbColorDepth );
+
+ if( rgbColorDepth == 24 || rgbColorDepth == 32 )
+ {
+ rgbChannelDepth = 8;
+ }
+ if( rgbColorDepth == 16 )
+ {
+ rgbChannelDepth = 5;
+ }
+
+ _glfwWin.redBits = rgbChannelDepth;
+ _glfwWin.greenBits = rgbChannelDepth;
+ _glfwWin.blueBits = rgbChannelDepth;
+
+ // Get pixel depth of accumulator - I haven't got the slightest idea
+ // how this number conforms to any other channel depth than 8 bits,
+ // so this might end up giving completely knackered results...
+ _getCGLAttribute( kCGLPFAColorSize, rgbaAccumDepth );
+ if( rgbaAccumDepth == 32 )
+ {
+ rgbaAccumDepth = 8;
+ }
+
+ _glfwWin.accumRedBits = rgbaAccumDepth;
+ _glfwWin.accumGreenBits = rgbaAccumDepth;
+ _glfwWin.accumBlueBits = rgbaAccumDepth;
+ _glfwWin.accumAlphaBits = rgbaAccumDepth;
+ }
+ else
+ {
+ _getAGLAttribute( AGL_ACCELERATED, _glfwWin.accelerated );
+ _getAGLAttribute( AGL_RED_SIZE, _glfwWin.redBits );
+ _getAGLAttribute( AGL_GREEN_SIZE, _glfwWin.greenBits );
+ _getAGLAttribute( AGL_BLUE_SIZE, _glfwWin.blueBits );
+ _getAGLAttribute( AGL_ALPHA_SIZE, _glfwWin.alphaBits );
+ _getAGLAttribute( AGL_DEPTH_SIZE, _glfwWin.depthBits );
+ _getAGLAttribute( AGL_STENCIL_SIZE, _glfwWin.stencilBits );
+ _getAGLAttribute( AGL_ACCUM_RED_SIZE, _glfwWin.accumRedBits );
+ _getAGLAttribute( AGL_ACCUM_GREEN_SIZE, _glfwWin.accumGreenBits );
+ _getAGLAttribute( AGL_ACCUM_BLUE_SIZE, _glfwWin.accumBlueBits );
+ _getAGLAttribute( AGL_ACCUM_ALPHA_SIZE, _glfwWin.accumAlphaBits );
+ _getAGLAttribute( AGL_AUX_BUFFERS, _glfwWin.auxBuffers );
+ _getAGLAttribute( AGL_STEREO, _glfwWin.stereo );
+ _getAGLAttribute( AGL_SAMPLES_ARB, _glfwWin.samples );
+ }
+}
+
+//========================================================================
+// Poll for new window and input events
+//========================================================================
+
+void _glfwPlatformPollEvents( void )
+{
+ EventRef event;
+ EventTargetRef eventDispatcher = GetEventDispatcherTarget();
+
+ while ( ReceiveNextEvent( 0, NULL, 0.0, TRUE, &event ) == noErr )
+ {
+ SendEventToEventTarget( event, eventDispatcher );
+ ReleaseEvent( event );
+ }
+}
+
+//========================================================================
+// Wait for new window and input events
+//========================================================================
+
+void _glfwPlatformWaitEvents( void )
+{
+ EventRef event;
+
+ // Wait for new events
+ ReceiveNextEvent( 0, NULL, kEventDurationForever, FALSE, &event );
+
+ // Process the new events
+ _glfwPlatformPollEvents();
+}
+
+//========================================================================
+// Hide mouse cursor (lock it)
+//========================================================================
+
+void _glfwPlatformHideMouseCursor( void )
+{
+ CGDisplayHideCursor( kCGDirectMainDisplay );
+ CGAssociateMouseAndMouseCursorPosition( false );
+}
+
+//========================================================================
+// Show mouse cursor (unlock it)
+//========================================================================
+
+void _glfwPlatformShowMouseCursor( void )
+{
+ CGDisplayShowCursor( kCGDirectMainDisplay );
+ CGAssociateMouseAndMouseCursorPosition( true );
+}
+
+//========================================================================
+// Set physical mouse cursor position
+//========================================================================
+
+void _glfwPlatformSetMouseCursorPos( int x, int y )
+{
+ Rect content;
+
+ if( _glfwWin.fullscreen )
+ {
+ CGDisplayMoveCursorToPoint( kCGDirectMainDisplay,
+ CGPointMake( x, y ) );
+ }
+ else
+ {
+ GetWindowBounds(_glfwWin.window, kWindowContentRgn, &content);
+
+ _glfwInput.MousePosX = x + content.left;
+ _glfwInput.MousePosY = y + content.top;
+
+ CGDisplayMoveCursorToPoint( kCGDirectMainDisplay,
+ CGPointMake( _glfwInput.MousePosX,
+ _glfwInput.MousePosY ) );
+ }
+}
+
diff --git a/lib/carbon/libglfw.pc.cmake b/lib/carbon/libglfw.pc.cmake
new file mode 100644
index 00000000..2700c59d
--- /dev/null
+++ b/lib/carbon/libglfw.pc.cmake
@@ -0,0 +1,11 @@
+prefix=@PREFIX@
+exec_prefix=@PREFIX@
+libdir=@PREFIX@/lib
+includedir=@PREFIX@/include
+
+Name: GLFW
+Description: A portable framework for OpenGL development
+Version: 2.7
+URL: http://glfw.sourceforge.net/
+Libs: -L${libdir} -lglfw -framework AGL -framework OpenGL -framework Carbon
+Cflags: -I${includedir}
diff --git a/lib/carbon/platform.h b/lib/carbon/platform.h
new file mode 100644
index 00000000..f39751c7
--- /dev/null
+++ b/lib/carbon/platform.h
@@ -0,0 +1,268 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Carbon/AGL/CGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2003 Keith Bauer
+// Copyright (c) 2003-2010 Camilla Berglund
+// Copyright (c) 2006-2007 Robin Leffmann
+//
+// 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 _platform_h_
+#define _platform_h_
+
+
+// This is the Mac OS X version of GLFW
+#define _GLFW_MAC_OS_X
+
+#include
+#include
+#include
+
+#include "../../include/GL/glfw.h"
+
+#if MACOSX_DEPLOYMENT_TARGET < MAC_OS_X_VERSION_10_3
+
+#ifndef kCGLNoError
+#define kCGLNoError 0
+#endif
+
+#endif
+
+
+#ifndef GL_VERSION_3_0
+
+typedef const GLubyte * (APIENTRY *PFNGLGETSTRINGIPROC) (GLenum, GLuint);
+
+#endif /*GL_VERSION_3_0*/
+
+
+//========================================================================
+// Defines
+//========================================================================
+
+#define _GLFW_MAX_PATH_LENGTH (8192)
+
+#define MAC_KEY_ENTER 0x24
+#define MAC_KEY_RETURN 0x34
+#define MAC_KEY_ESC 0x35
+#define MAC_KEY_F1 0x7A
+#define MAC_KEY_F2 0x78
+#define MAC_KEY_F3 0x63
+#define MAC_KEY_F4 0x76
+#define MAC_KEY_F5 0x60
+#define MAC_KEY_F6 0x61
+#define MAC_KEY_F7 0x62
+#define MAC_KEY_F8 0x64
+#define MAC_KEY_F9 0x65
+#define MAC_KEY_F10 0x6D
+#define MAC_KEY_F11 0x67
+#define MAC_KEY_F12 0x6F
+#define MAC_KEY_F13 0x69
+#define MAC_KEY_F14 0x6B
+#define MAC_KEY_F15 0x71
+#define MAC_KEY_UP 0x7E
+#define MAC_KEY_DOWN 0x7D
+#define MAC_KEY_LEFT 0x7B
+#define MAC_KEY_RIGHT 0x7C
+#define MAC_KEY_TAB 0x30
+#define MAC_KEY_BACKSPACE 0x33
+#define MAC_KEY_HELP 0x72
+#define MAC_KEY_DEL 0x75
+#define MAC_KEY_PAGEUP 0x74
+#define MAC_KEY_PAGEDOWN 0x79
+#define MAC_KEY_HOME 0x73
+#define MAC_KEY_END 0x77
+#define MAC_KEY_KP_0 0x52
+#define MAC_KEY_KP_1 0x53
+#define MAC_KEY_KP_2 0x54
+#define MAC_KEY_KP_3 0x55
+#define MAC_KEY_KP_4 0x56
+#define MAC_KEY_KP_5 0x57
+#define MAC_KEY_KP_6 0x58
+#define MAC_KEY_KP_7 0x59
+#define MAC_KEY_KP_8 0x5B
+#define MAC_KEY_KP_9 0x5C
+#define MAC_KEY_KP_DIVIDE 0x4B
+#define MAC_KEY_KP_MULTIPLY 0x43
+#define MAC_KEY_KP_SUBTRACT 0x4E
+#define MAC_KEY_KP_ADD 0x45
+#define MAC_KEY_KP_DECIMAL 0x41
+#define MAC_KEY_KP_EQUAL 0x51
+#define MAC_KEY_KP_ENTER 0x4C
+#define MAC_KEY_NUMLOCK 0x47
+
+
+//========================================================================
+// GLFW platform specific types
+//========================================================================
+
+//------------------------------------------------------------------------
+// Pointer length integer
+//------------------------------------------------------------------------
+typedef intptr_t GLFWintptr;
+
+
+GLFWGLOBAL CFDictionaryRef _glfwDesktopVideoMode;
+
+//------------------------------------------------------------------------
+// Window structure
+//------------------------------------------------------------------------
+typedef struct _GLFWwin_struct _GLFWwin;
+
+struct _GLFWwin_struct {
+
+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
+
+ // User callback functions
+ GLFWwindowsizefun windowSizeCallback;
+ GLFWwindowclosefun windowCloseCallback;
+ GLFWwindowrefreshfun windowRefreshCallback;
+ GLFWmousebuttonfun mouseButtonCallback;
+ GLFWmouseposfun mousePosCallback;
+ GLFWmousewheelfun mouseWheelCallback;
+ GLFWkeyfun keyCallback;
+ GLFWcharfun charCallback;
+
+ // User selected window settings
+ int fullscreen; // Fullscreen flag
+ int mouseLock; // Mouse-lock flag
+ int autoPollEvents; // Auto polling flag
+ int sysKeysDisabled; // System keys disabled flag
+ int windowNoResize; // Resize- and maximize gadgets disabled flag
+ int refreshRate; // Vertical monitor refresh rate
+
+ // Window status & parameters
+ int opened; // Flag telling if window is opened or not
+ int active; // Application active flag
+ int iconified; // Window iconified flag
+ int width, height; // Window width and heigth
+ int accelerated; // GL_TRUE if window is HW accelerated
+
+ // Framebuffer attributes
+ int redBits;
+ int greenBits;
+ int blueBits;
+ int alphaBits;
+ int depthBits;
+ int stencilBits;
+ int accumRedBits;
+ int accumGreenBits;
+ int accumBlueBits;
+ int accumAlphaBits;
+ int auxBuffers;
+ int stereo;
+ int samples;
+
+ // OpenGL extensions and context attributes
+ int has_GL_SGIS_generate_mipmap;
+ int has_GL_ARB_texture_non_power_of_two;
+ int glMajor, glMinor, glRevision;
+ int glForward, glDebug, glProfile;
+
+ PFNGLGETSTRINGIPROC GetStringi;
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+ WindowRef window;
+
+ AGLContext aglContext;
+ AGLPixelFormat aglPixelFormat;
+
+ CGLContextObj cglContext;
+ CGLPixelFormatObj cglPixelFormat;
+
+ EventHandlerUPP windowUPP;
+ EventHandlerUPP mouseUPP;
+ EventHandlerUPP commandUPP;
+ EventHandlerUPP keyboardUPP;
+};
+
+GLFWGLOBAL _GLFWwin _glfwWin;
+
+
+//------------------------------------------------------------------------
+// User input status (some of this should go in _GLFWwin)
+//------------------------------------------------------------------------
+GLFWGLOBAL struct {
+
+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
+
+ // Mouse status
+ int MousePosX, MousePosY;
+ int WheelPos;
+ char MouseButton[ GLFW_MOUSE_BUTTON_LAST + 1 ];
+
+ // Keyboard status
+ char Key[ GLFW_KEY_LAST + 1 ];
+ int LastChar;
+
+ // User selected settings
+ int StickyKeys;
+ int StickyMouseButtons;
+ int KeyRepeat;
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+ UInt32 Modifiers;
+
+} _glfwInput;
+
+
+
+//------------------------------------------------------------------------
+// Library global data
+//------------------------------------------------------------------------
+GLFWGLOBAL struct {
+
+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
+
+ // Window opening hints
+ _GLFWhints hints;
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+ // Timer data
+ struct {
+ double t0;
+ } Timer;
+
+ struct {
+ // Bundle for dynamically-loading extension function pointers
+ CFBundleRef OpenGLFramework;
+ } Libs;
+
+ int Unbundled;
+
+} _glfwLibrary;
+
+
+//========================================================================
+// Prototypes for platform specific internal functions
+//========================================================================
+
+void _glfwChangeToResourcesDirectory( void );
+
+#endif // _platform_h_
diff --git a/lib/cocoa/CMakeLists.txt b/lib/cocoa/CMakeLists.txt
new file mode 100644
index 00000000..115e9bf2
--- /dev/null
+++ b/lib/cocoa/CMakeLists.txt
@@ -0,0 +1,44 @@
+
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/libglfw.pc.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/libglfw.pc @ONLY)
+
+include_directories(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_SOURCE_DIR}/lib
+ ${GLFW_INCLUDE_DIR})
+
+set(cocoa_SOURCES
+ cocoa_enable.m
+ cocoa_fullscreen.m
+ cocoa_glext.m
+ cocoa_init.m
+ cocoa_joystick.m
+ cocoa_time.m
+ cocoa_window.m)
+
+# For some reason, CMake doesn't know about .m
+set_source_files_properties(${cocoa_SOURCES} PROPERTIES LANGUAGE C)
+
+set(libglfw_SOURCES
+ ${common_SOURCES}
+ ${cocoa_SOURCES})
+
+add_library(libglfwStatic STATIC ${libglfw_SOURCES})
+add_library(libglfwShared SHARED ${libglfw_SOURCES})
+target_link_libraries(libglfwShared ${GLFW_LIBRARIES})
+set_target_properties(libglfwStatic libglfwShared PROPERTIES
+ CLEAN_DIRECT_OUTPUT 1
+ OUTPUT_NAME glfw
+)
+
+# Append -fno-common to the compile flags to work around a bug in the Apple GCC
+get_target_property(CFLAGS libglfwShared COMPILE_FLAGS)
+if(NOT CFLAGS)
+ set(CFLAGS "")
+endif(NOT CFLAGS)
+set_target_properties(libglfwShared PROPERTIES COMPILE_FLAGS "${CFLAGS} -fno-common")
+
+install(TARGETS libglfwStatic libglfwShared DESTINATION lib)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libglfw.pc DESTINATION lib/pkgconfig)
+
diff --git a/lib/cocoa/cocoa_enable.m b/lib/cocoa/cocoa_enable.m
new file mode 100644
index 00000000..7e194766
--- /dev/null
+++ b/lib/cocoa/cocoa_enable.m
@@ -0,0 +1,51 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund
+//
+// 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"
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Enable and disable system keys
+//========================================================================
+
+void _glfwPlatformEnableSystemKeys( void )
+{
+ // This is checked in macosx_window.m; we take no action here
+}
+
+void _glfwPlatformDisableSystemKeys( void )
+{
+ // This is checked in macosx_window.m; we take no action here
+ // I don't think it's really possible to disable stuff like Exposé
+ // except in full-screen mode.
+}
+
diff --git a/lib/cocoa/cocoa_fullscreen.m b/lib/cocoa/cocoa_fullscreen.m
new file mode 100644
index 00000000..e716cee7
--- /dev/null
+++ b/lib/cocoa/cocoa_fullscreen.m
@@ -0,0 +1,102 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund
+//
+// 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"
+
+//========================================================================
+// Check whether the display mode should be included in enumeration
+//========================================================================
+
+static BOOL modeIsGood( NSDictionary *mode )
+{
+ // This is a bit controversial, if you've got something other than an
+ // LCD computer monitor as an output device you might not want these
+ // checks. You might also want to reject modes which are interlaced,
+ // or TV out. There is no one-size-fits-all policy that can work here.
+ // This seems like a decent compromise, but certain applications may
+ // wish to patch this...
+ return [[mode objectForKey:(id)kCGDisplayBitsPerPixel] intValue] >= 15 &&
+ [mode objectForKey:(id)kCGDisplayModeIsSafeForHardware] != nil &&
+ [mode objectForKey:(id)kCGDisplayModeIsStretched] == nil;
+}
+
+//========================================================================
+// Convert Core Graphics display mode to GLFW video mode
+//========================================================================
+
+static GLFWvidmode vidmodeFromCGDisplayMode( NSDictionary *mode )
+{
+ unsigned int width = [[mode objectForKey:(id)kCGDisplayWidth] unsignedIntValue];
+ unsigned int height = [[mode objectForKey:(id)kCGDisplayHeight] unsignedIntValue];
+ unsigned int bps = [[mode objectForKey:(id)kCGDisplayBitsPerSample] unsignedIntValue];
+
+ GLFWvidmode result;
+ result.Width = width;
+ result.Height = height;
+ result.RedBits = bps;
+ result.GreenBits = bps;
+ result.BlueBits = bps;
+ return result;
+}
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Get a list of available video modes
+//========================================================================
+
+int _glfwPlatformGetVideoModes( GLFWvidmode *list, int maxcount )
+{
+ NSArray *modes = (NSArray *)CGDisplayAvailableModes( CGMainDisplayID() );
+
+ unsigned int i, j = 0, n = [modes count];
+ for( i = 0; i < n && i < (unsigned)maxcount; i++ )
+ {
+ NSDictionary *mode = [modes objectAtIndex:i];
+ if( modeIsGood( mode ) )
+ {
+ list[j++] = vidmodeFromCGDisplayMode( mode );
+ }
+ }
+
+ return j;
+}
+
+//========================================================================
+// Get the desktop video mode
+//========================================================================
+
+void _glfwPlatformGetDesktopMode( GLFWvidmode *mode )
+{
+ *mode = vidmodeFromCGDisplayMode( _glfwLibrary.DesktopMode );
+}
+
diff --git a/lib/cocoa/cocoa_glext.m b/lib/cocoa/cocoa_glext.m
new file mode 100644
index 00000000..860b0041
--- /dev/null
+++ b/lib/cocoa/cocoa_glext.m
@@ -0,0 +1,63 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund
+//
+// 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"
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Check if an OpenGL extension is available at runtime
+//========================================================================
+
+int _glfwPlatformExtensionSupported( const char *extension )
+{
+ // There are no AGL, CGL or NSGL extensions.
+ return GL_FALSE;
+}
+
+//========================================================================
+// Get the function pointer to an OpenGL function
+//========================================================================
+
+void * _glfwPlatformGetProcAddress( const char *procname )
+{
+ CFStringRef symbolName = CFStringCreateWithCString( kCFAllocatorDefault,
+ procname,
+ kCFStringEncodingASCII );
+
+ void *symbol = CFBundleGetFunctionPointerForName( _glfwLibrary.OpenGLFramework,
+ symbolName );
+
+ CFRelease( symbolName );
+
+ return symbol;
+}
+
diff --git a/lib/cocoa/cocoa_init.m b/lib/cocoa/cocoa_init.m
new file mode 100644
index 00000000..94cf1293
--- /dev/null
+++ b/lib/cocoa/cocoa_init.m
@@ -0,0 +1,250 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund
+//
+// 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.
+//
+//========================================================================
+
+// Needed for _NSGetProgname
+#include
+
+#include "internal.h"
+
+@interface GLFWApplication : NSApplication
+@end
+
+@implementation GLFWApplication
+
+// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost
+// This works around an AppKit bug, where key up events while holding
+// down the command key don't get sent to the key window.
+- (void)sendEvent:(NSEvent *)event
+{
+ if( [event type] == NSKeyUp && ( [event modifierFlags] & NSCommandKeyMask ) )
+ {
+ [[self keyWindow] sendEvent:event];
+ }
+ else
+ {
+ [super sendEvent:event];
+ }
+}
+
+@end
+
+// Prior to Snow Leopard, we need to use this oddly-named semi-private API
+// to get the application menu working properly. Need to be careful in
+// case it goes away in a future OS update.
+@interface NSApplication (NSAppleMenu)
+- (void)setAppleMenu:(NSMenu *)m;
+@end
+
+// Keys to search for as potential application names
+NSString *GLFWNameKeys[] =
+{
+ @"CFBundleDisplayName",
+ @"CFBundleName",
+ @"CFBundleExecutable",
+};
+
+//========================================================================
+// Try to figure out what the calling application is called
+//========================================================================
+static NSString *findAppName( void )
+{
+ NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
+
+ unsigned int i;
+ for( i = 0; i < sizeof(GLFWNameKeys) / sizeof(GLFWNameKeys[0]); i++ )
+ {
+ id name = [infoDictionary objectForKey:GLFWNameKeys[i]];
+ if (name &&
+ [name isKindOfClass:[NSString class]] &&
+ ![@"" isEqualToString:name])
+ {
+ return name;
+ }
+ }
+
+ // If we get here, we're unbundled
+ if( !_glfwLibrary.Unbundled )
+ {
+ // Could do this only if we discover we're unbundled, but it should
+ // do no harm...
+ ProcessSerialNumber psn = { 0, kCurrentProcess };
+ TransformProcessType( &psn, kProcessTransformToForegroundApplication );
+
+ // Having the app in front of the terminal window is also generally
+ // handy. There is an NSApplication API to do this, but...
+ SetFrontProcess( &psn );
+
+ _glfwLibrary.Unbundled = GL_TRUE;
+ }
+
+ char **progname = _NSGetProgname();
+ if( progname && *progname )
+ {
+ // TODO: UTF8?
+ return [NSString stringWithUTF8String:*progname];
+ }
+
+ // Really shouldn't get here
+ return @"GLFW Application";
+}
+
+//========================================================================
+// Set up the menu bar (manually)
+// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
+// could go away at any moment, lots of stuff that really should be
+// localize(d|able), etc. Loading a nib would save us this horror, but that
+// doesn't seem like a good thing to require of GLFW's clients.
+//========================================================================
+static void setUpMenuBar( void )
+{
+ NSString *appName = findAppName();
+
+ NSMenu *bar = [[NSMenu alloc] init];
+ [NSApp setMainMenu:bar];
+
+ NSMenuItem *appMenuItem =
+ [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
+ NSMenu *appMenu = [[NSMenu alloc] init];
+ [appMenuItem setSubmenu:appMenu];
+
+ [appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName]
+ action:@selector(orderFrontStandardAboutPanel:)
+ keyEquivalent:@""];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+ NSMenu *servicesMenu = [[NSMenu alloc] init];
+ [NSApp setServicesMenu:servicesMenu];
+ [[appMenu addItemWithTitle:@"Services"
+ action:NULL
+ keyEquivalent:@""] setSubmenu:servicesMenu];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+ [appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
+ action:@selector(hide:)
+ keyEquivalent:@"h"];
+ [[appMenu addItemWithTitle:@"Hide Others"
+ action:@selector(hideOtherApplications:)
+ keyEquivalent:@"h"]
+ setKeyEquivalentModifierMask:NSAlternateKeyMask | NSCommandKeyMask];
+ [appMenu addItemWithTitle:@"Show All"
+ action:@selector(unhideAllApplications:)
+ keyEquivalent:@""];
+ [appMenu addItem:[NSMenuItem separatorItem]];
+ [appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
+ action:@selector(terminate:)
+ keyEquivalent:@"q"];
+
+ NSMenuItem *windowMenuItem =
+ [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
+ NSMenu *windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+ [NSApp setWindowsMenu:windowMenu];
+ [windowMenuItem setSubmenu:windowMenu];
+
+ [windowMenu addItemWithTitle:@"Miniaturize"
+ action:@selector(performMiniaturize:)
+ keyEquivalent:@"m"];
+ [windowMenu addItemWithTitle:@"Zoom"
+ action:@selector(performZoom:)
+ keyEquivalent:@""];
+ [windowMenu addItem:[NSMenuItem separatorItem]];
+ [windowMenu addItemWithTitle:@"Bring All to Front"
+ action:@selector(arrangeInFront:)
+ keyEquivalent:@""];
+
+ // At least guard the call to private API to avoid an exception if it
+ // goes away. Hopefully that means the worst we'll break in future is to
+ // look ugly...
+ if( [NSApp respondsToSelector:@selector(setAppleMenu:)] )
+ {
+ [NSApp setAppleMenu:appMenu];
+ }
+}
+
+//========================================================================
+// Terminate GLFW when exiting application
+//========================================================================
+
+static void glfw_atexit( void )
+{
+ glfwTerminate();
+}
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Initialize the GLFW library
+//========================================================================
+
+int _glfwPlatformInit( void )
+{
+ _glfwLibrary.AutoreleasePool = [[NSAutoreleasePool alloc] init];
+
+ // Implicitly create shared NSApplication instance
+ [GLFWApplication sharedApplication];
+
+ NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
+
+ if( access( [resourcePath cStringUsingEncoding:NSUTF8StringEncoding], R_OK ) == 0 )
+ {
+ chdir( [resourcePath cStringUsingEncoding:NSUTF8StringEncoding] );
+ }
+
+ // Setting up menu bar must go exactly here else weirdness ensues
+ setUpMenuBar();
+
+ [NSApp finishLaunching];
+
+ // Install atexit routine
+ atexit( glfw_atexit );
+
+ _glfwPlatformSetTime( 0.0 );
+
+ _glfwLibrary.DesktopMode =
+ (NSDictionary *)CGDisplayCurrentMode( CGMainDisplayID() );
+
+ return GL_TRUE;
+}
+
+//========================================================================
+// Close window, if open, and shut down GLFW
+//========================================================================
+
+int _glfwPlatformTerminate( void )
+{
+ glfwCloseWindow();
+
+ // TODO: Probably other cleanup
+
+ [_glfwLibrary.AutoreleasePool release];
+ _glfwLibrary.AutoreleasePool = nil;
+
+ return GL_TRUE;
+}
+
diff --git a/lib/cocoa/cocoa_joystick.m b/lib/cocoa/cocoa_joystick.m
new file mode 100644
index 00000000..bd3ea640
--- /dev/null
+++ b/lib/cocoa/cocoa_joystick.m
@@ -0,0 +1,65 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund
+//
+// 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"
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Determine joystick capabilities
+//========================================================================
+
+int _glfwPlatformGetJoystickParam( int joy, int param )
+{
+ // TODO: Implement this.
+ return 0;
+}
+
+//========================================================================
+// Get joystick axis positions
+//========================================================================
+
+int _glfwPlatformGetJoystickPos( int joy, float *pos, int numaxes )
+{
+ // TODO: Implement this.
+ return 0;
+}
+
+//========================================================================
+// Get joystick button states
+//========================================================================
+
+int _glfwPlatformGetJoystickButtons( int joy, unsigned char *buttons, int numbuttons )
+{
+ // TODO: Implement this.
+ return 0;
+}
+
diff --git a/lib/cocoa/cocoa_time.m b/lib/cocoa/cocoa_time.m
new file mode 100644
index 00000000..df68b24b
--- /dev/null
+++ b/lib/cocoa/cocoa_time.m
@@ -0,0 +1,53 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund
+//
+// 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"
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Return timer value in seconds
+//========================================================================
+
+double _glfwPlatformGetTime( void )
+{
+ return [NSDate timeIntervalSinceReferenceDate] - _glfwLibrary.Timer.t0;
+}
+
+//========================================================================
+// Set timer value in seconds
+//========================================================================
+
+void _glfwPlatformSetTime( double time )
+{
+ _glfwLibrary.Timer.t0 = [NSDate timeIntervalSinceReferenceDate] - time;
+}
+
diff --git a/lib/cocoa/cocoa_window.m b/lib/cocoa/cocoa_window.m
new file mode 100644
index 00000000..7bc0b996
--- /dev/null
+++ b/lib/cocoa/cocoa_window.m
@@ -0,0 +1,886 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund
+//
+// 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"
+
+//========================================================================
+// Delegate for window related notifications
+// (but also used as an application delegate)
+//========================================================================
+
+@interface GLFWWindowDelegate : NSObject
+@end
+
+@implementation GLFWWindowDelegate
+
+- (BOOL)windowShouldClose:(id)window
+{
+ if( _glfwWin.windowCloseCallback )
+ {
+ if( !_glfwWin.windowCloseCallback() )
+ {
+ return NO;
+ }
+ }
+
+ // This is horribly ugly, but it works
+ glfwCloseWindow();
+ return NO;
+}
+
+- (void)windowDidResize:(NSNotification *)notification
+{
+ [_glfwWin.context update];
+
+ NSRect contentRect =
+ [_glfwWin.window contentRectForFrameRect:[_glfwWin.window frame]];
+ _glfwWin.width = contentRect.size.width;
+ _glfwWin.height = contentRect.size.height;
+
+ if( _glfwWin.windowSizeCallback )
+ {
+ _glfwWin.windowSizeCallback( _glfwWin.width, _glfwWin.height );
+ }
+}
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
+{
+ if( _glfwWin.windowCloseCallback )
+ {
+ if( !_glfwWin.windowCloseCallback() )
+ {
+ return NSTerminateCancel;
+ }
+ }
+
+ // This is horribly ugly, but it works
+ glfwCloseWindow();
+ return NSTerminateCancel;
+}
+
+@end
+
+// TODO: Need to find mappings for F13-F15, volume down/up/mute, and eject.
+static const unsigned int MAC_TO_GLFW_KEYCODE_MAPPING[128] =
+{
+ /* 00 */ 'A',
+ /* 01 */ 'S',
+ /* 02 */ 'D',
+ /* 03 */ 'F',
+ /* 04 */ 'H',
+ /* 05 */ 'G',
+ /* 06 */ 'Z',
+ /* 07 */ 'X',
+ /* 08 */ 'C',
+ /* 09 */ 'V',
+ /* 0a */ -1,
+ /* 0b */ 'B',
+ /* 0c */ 'Q',
+ /* 0d */ 'W',
+ /* 0e */ 'E',
+ /* 0f */ 'R',
+ /* 10 */ 'Y',
+ /* 11 */ 'T',
+ /* 12 */ '1',
+ /* 13 */ '2',
+ /* 14 */ '3',
+ /* 15 */ '4',
+ /* 16 */ '6',
+ /* 17 */ '5',
+ /* 18 */ '=',
+ /* 19 */ '9',
+ /* 1a */ '7',
+ /* 1b */ '-',
+ /* 1c */ '8',
+ /* 1d */ '0',
+ /* 1e */ ']',
+ /* 1f */ 'O',
+ /* 20 */ 'U',
+ /* 21 */ '[',
+ /* 22 */ 'I',
+ /* 23 */ 'P',
+ /* 24 */ GLFW_KEY_ENTER,
+ /* 25 */ 'L',
+ /* 26 */ 'J',
+ /* 27 */ '\'',
+ /* 28 */ 'K',
+ /* 29 */ ';',
+ /* 2a */ '\\',
+ /* 2b */ ',',
+ /* 2c */ '/',
+ /* 2d */ 'N',
+ /* 2e */ 'M',
+ /* 2f */ '.',
+ /* 30 */ GLFW_KEY_TAB,
+ /* 31 */ GLFW_KEY_SPACE,
+ /* 32 */ '`',
+ /* 33 */ GLFW_KEY_BACKSPACE,
+ /* 34 */ -1,
+ /* 35 */ GLFW_KEY_ESC,
+ /* 36 */ GLFW_KEY_RSUPER,
+ /* 37 */ GLFW_KEY_LSUPER,
+ /* 38 */ GLFW_KEY_LSHIFT,
+ /* 39 */ GLFW_KEY_CAPS_LOCK,
+ /* 3a */ GLFW_KEY_LALT,
+ /* 3b */ GLFW_KEY_LCTRL,
+ /* 3c */ GLFW_KEY_RSHIFT,
+ /* 3d */ GLFW_KEY_RALT,
+ /* 3e */ GLFW_KEY_RCTRL,
+ /* 3f */ -1, /*Function*/
+ /* 40 */ GLFW_KEY_F17,
+ /* 41 */ GLFW_KEY_KP_DECIMAL,
+ /* 42 */ -1,
+ /* 43 */ GLFW_KEY_KP_MULTIPLY,
+ /* 44 */ -1,
+ /* 45 */ GLFW_KEY_KP_ADD,
+ /* 46 */ -1,
+ /* 47 */ -1, /*KeypadClear*/
+ /* 48 */ -1, /*VolumeUp*/
+ /* 49 */ -1, /*VolumeDown*/
+ /* 4a */ -1, /*Mute*/
+ /* 4b */ GLFW_KEY_KP_DIVIDE,
+ /* 4c */ GLFW_KEY_KP_ENTER,
+ /* 4d */ -1,
+ /* 4e */ GLFW_KEY_KP_SUBTRACT,
+ /* 4f */ GLFW_KEY_F18,
+ /* 50 */ GLFW_KEY_F19,
+ /* 51 */ GLFW_KEY_KP_EQUAL,
+ /* 52 */ GLFW_KEY_KP_0,
+ /* 53 */ GLFW_KEY_KP_1,
+ /* 54 */ GLFW_KEY_KP_2,
+ /* 55 */ GLFW_KEY_KP_3,
+ /* 56 */ GLFW_KEY_KP_4,
+ /* 57 */ GLFW_KEY_KP_5,
+ /* 58 */ GLFW_KEY_KP_6,
+ /* 59 */ GLFW_KEY_KP_7,
+ /* 5a */ GLFW_KEY_F20,
+ /* 5b */ GLFW_KEY_KP_8,
+ /* 5c */ GLFW_KEY_KP_9,
+ /* 5d */ -1,
+ /* 5e */ -1,
+ /* 5f */ -1,
+ /* 60 */ GLFW_KEY_F5,
+ /* 61 */ GLFW_KEY_F6,
+ /* 62 */ GLFW_KEY_F7,
+ /* 63 */ GLFW_KEY_F3,
+ /* 64 */ GLFW_KEY_F8,
+ /* 65 */ GLFW_KEY_F9,
+ /* 66 */ -1,
+ /* 67 */ GLFW_KEY_F11,
+ /* 68 */ -1,
+ /* 69 */ GLFW_KEY_F13,
+ /* 6a */ GLFW_KEY_F16,
+ /* 6b */ GLFW_KEY_F14,
+ /* 6c */ -1,
+ /* 6d */ GLFW_KEY_F10,
+ /* 6e */ -1,
+ /* 6f */ GLFW_KEY_F12,
+ /* 70 */ -1,
+ /* 71 */ GLFW_KEY_F15,
+ /* 72 */ GLFW_KEY_INSERT, /*Help*/
+ /* 73 */ GLFW_KEY_HOME,
+ /* 74 */ GLFW_KEY_PAGEUP,
+ /* 75 */ GLFW_KEY_DEL,
+ /* 76 */ GLFW_KEY_F4,
+ /* 77 */ GLFW_KEY_END,
+ /* 78 */ GLFW_KEY_F2,
+ /* 79 */ GLFW_KEY_PAGEDOWN,
+ /* 7a */ GLFW_KEY_F1,
+ /* 7b */ GLFW_KEY_LEFT,
+ /* 7c */ GLFW_KEY_RIGHT,
+ /* 7d */ GLFW_KEY_DOWN,
+ /* 7e */ GLFW_KEY_UP,
+ /* 7f */ -1,
+};
+
+//========================================================================
+// Converts a Mac OS X keycode to a GLFW keycode
+//========================================================================
+
+static int convertMacKeyCode( unsigned int macKeyCode )
+{
+ if( macKeyCode >= 128 )
+ {
+ return -1;
+ }
+
+ // This treats keycodes as *positional*; that is, we'll return 'a'
+ // for the key left of 's', even on an AZERTY keyboard. The charInput
+ // function should still get 'q' though.
+ return MAC_TO_GLFW_KEYCODE_MAPPING[macKeyCode];
+}
+
+//========================================================================
+// Content view class for the GLFW window
+//========================================================================
+
+@interface GLFWContentView : NSView
+@end
+
+@implementation GLFWContentView
+
+- (BOOL)isOpaque
+{
+ return YES;
+}
+
+- (BOOL)canBecomeKeyView
+{
+ return YES;
+}
+
+- (BOOL)acceptsFirstResponder
+{
+ return YES;
+}
+
+- (void)mouseDown:(NSEvent *)event
+{
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS );
+}
+
+- (void)mouseDragged:(NSEvent *)event
+{
+ [self mouseMoved:event];
+}
+
+- (void)mouseUp:(NSEvent *)event
+{
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE );
+}
+
+- (void)mouseMoved:(NSEvent *)event
+{
+ if( _glfwWin.mouseLock )
+ {
+ _glfwInput.MousePosX += [event deltaX];
+ _glfwInput.MousePosY += [event deltaY];
+ }
+ else
+ {
+ NSPoint p = [event locationInWindow];
+
+ // Cocoa coordinate system has origin at lower left
+ _glfwInput.MousePosX = p.x;
+ _glfwInput.MousePosY = [[_glfwWin.window contentView] bounds].size.height - p.y;
+ }
+
+ if( _glfwWin.mousePosCallback )
+ {
+ _glfwWin.mousePosCallback( _glfwInput.MousePosX, _glfwInput.MousePosY );
+ }
+}
+
+- (void)rightMouseDown:(NSEvent *)event
+{
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS );
+}
+
+- (void)rightMouseDragged:(NSEvent *)event
+{
+ [self mouseMoved:event];
+}
+
+- (void)rightMouseUp:(NSEvent *)event
+{
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE );
+}
+
+- (void)otherMouseDown:(NSEvent *)event
+{
+ _glfwInputMouseClick( [event buttonNumber], GLFW_PRESS );
+}
+
+- (void)otherMouseDragged:(NSEvent *)event
+{
+ [self mouseMoved:event];
+}
+
+- (void)otherMouseUp:(NSEvent *)event
+{
+ _glfwInputMouseClick( [event buttonNumber], GLFW_RELEASE );
+}
+
+- (void)keyDown:(NSEvent *)event
+{
+ NSUInteger length;
+ NSString* characters;
+ int i, code = convertMacKeyCode( [event keyCode] );
+
+ if( code != -1 )
+ {
+ _glfwInputKey( code, GLFW_PRESS );
+
+ if( [event modifierFlags] & NSCommandKeyMask )
+ {
+ if( !_glfwWin.sysKeysDisabled )
+ {
+ [super keyDown:event];
+ }
+ }
+ else
+ {
+ characters = [event characters];
+ length = [characters length];
+
+ for( i = 0; i < length; i++ )
+ {
+ _glfwInputChar( [characters characterAtIndex:i], GLFW_PRESS );
+ }
+ }
+ }
+}
+
+- (void)flagsChanged:(NSEvent *)event
+{
+ unsigned int newModifierFlags = [event modifierFlags] | NSDeviceIndependentModifierFlagsMask;
+ int mode;
+
+ if( newModifierFlags > _glfwWin.modifierFlags )
+ {
+ mode = GLFW_PRESS;
+ }
+ else
+ {
+ mode = GLFW_RELEASE;
+ }
+
+ _glfwWin.modifierFlags = newModifierFlags;
+ _glfwInputKey( MAC_TO_GLFW_KEYCODE_MAPPING[[event keyCode]], mode );
+}
+
+- (void)keyUp:(NSEvent *)event
+{
+ NSUInteger length;
+ NSString* characters;
+ int i, code = convertMacKeyCode( [event keyCode] );
+
+ if( code != -1 )
+ {
+ _glfwInputKey( code, GLFW_RELEASE );
+
+ characters = [event characters];
+ length = [characters length];
+
+ for( i = 0; i < length; i++ )
+ {
+ _glfwInputChar( [characters characterAtIndex:i], GLFW_RELEASE );
+ }
+ }
+}
+
+- (void)scrollWheel:(NSEvent *)event
+{
+ _glfwInput.WheelPosFloating += [event deltaY];
+ _glfwInput.WheelPos = lrint(_glfwInput.WheelPosFloating);
+
+ if( _glfwWin.mouseWheelCallback )
+ {
+ _glfwWin.mouseWheelCallback( _glfwInput.WheelPos );
+ }
+}
+
+@end
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Here is where the window is created, and the OpenGL rendering context is
+// created
+//========================================================================
+
+int _glfwPlatformOpenWindow( int width, int height,
+ const _GLFWwndconfig *wndconfig,
+ const _GLFWfbconfig *fbconfig )
+{
+ int colorBits;
+
+ _glfwWin.pixelFormat = nil;
+ _glfwWin.window = nil;
+ _glfwWin.context = nil;
+ _glfwWin.delegate = nil;
+
+ // Fail if OpenGL 3.0 or above was requested
+ if( wndconfig->glMajor > 2 )
+ {
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ _glfwWin.delegate = [[GLFWWindowDelegate alloc] init];
+ if( _glfwWin.delegate == nil )
+ {
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ [NSApp setDelegate:_glfwWin.delegate];
+
+ // Mac OS X needs non-zero color size, so set resonable values
+ colorBits = fbconfig->redBits + fbconfig->greenBits + fbconfig->blueBits;
+ if( colorBits == 0 )
+ {
+ colorBits = 24;
+ }
+ else if( colorBits < 15 )
+ {
+ colorBits = 15;
+ }
+
+ // Ignored hints:
+ // OpenGLMajor, OpenGLMinor, OpenGLForward:
+ // pending Mac OS X support for OpenGL 3.x
+ // OpenGLDebug
+ // pending it meaning anything on Mac OS X
+
+ // Don't use accumulation buffer support; it's not accelerated
+ // Aux buffers probably aren't accelerated either
+
+ CFDictionaryRef fullscreenMode = NULL;
+ if( wndconfig->mode == GLFW_FULLSCREEN )
+ {
+ fullscreenMode =
+ // I think it's safe to pass 0 to the refresh rate for this function
+ // rather than conditionalizing the code to call the version which
+ // doesn't specify refresh...
+ CGDisplayBestModeForParametersAndRefreshRateWithProperty(
+ CGMainDisplayID(),
+ colorBits + fbconfig->alphaBits,
+ width,
+ height,
+ wndconfig->refreshRate,
+ // Controversial, see macosx_fullscreen.m for discussion
+ kCGDisplayModeIsSafeForHardware,
+ NULL);
+
+ width = [[(id)fullscreenMode objectForKey:(id)kCGDisplayWidth] intValue];
+ height = [[(id)fullscreenMode objectForKey:(id)kCGDisplayHeight] intValue];
+ }
+
+ unsigned int styleMask = 0;
+ if( wndconfig->mode == GLFW_WINDOW )
+ {
+ styleMask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask;
+
+ if( !wndconfig->windowNoResize )
+ {
+ styleMask |= NSResizableWindowMask;
+ }
+ }
+ else
+ {
+ styleMask = NSBorderlessWindowMask;
+ }
+
+ _glfwWin.window = [[NSWindow alloc]
+ initWithContentRect:NSMakeRect(0, 0, width, height)
+ styleMask:styleMask
+ backing:NSBackingStoreBuffered
+ defer:NO];
+ [_glfwWin.window setContentView:[[GLFWContentView alloc] init]];
+ [_glfwWin.window setDelegate:_glfwWin.delegate];
+ [_glfwWin.window setAcceptsMouseMovedEvents:YES];
+ [_glfwWin.window center];
+
+ if( wndconfig->mode == GLFW_FULLSCREEN )
+ {
+ CGCaptureAllDisplays();
+ CGDisplaySwitchToMode( CGMainDisplayID(), fullscreenMode );
+ }
+
+ unsigned int attribute_count = 0;
+#define ADD_ATTR(x) attributes[attribute_count++] = x
+#define ADD_ATTR2(x, y) (void)({ ADD_ATTR(x); ADD_ATTR(y); })
+#define MAX_ATTRS 24 // urgh
+ NSOpenGLPixelFormatAttribute attributes[MAX_ATTRS];
+
+ ADD_ATTR( NSOpenGLPFADoubleBuffer );
+
+ if( wndconfig->mode == GLFW_FULLSCREEN )
+ {
+ ADD_ATTR( NSOpenGLPFAFullScreen );
+ ADD_ATTR( NSOpenGLPFANoRecovery );
+ ADD_ATTR2( NSOpenGLPFAScreenMask,
+ CGDisplayIDToOpenGLDisplayMask( CGMainDisplayID() ) );
+ }
+
+ ADD_ATTR2( NSOpenGLPFAColorSize, colorBits );
+
+ if( fbconfig->alphaBits > 0)
+ {
+ ADD_ATTR2( NSOpenGLPFAAlphaSize, fbconfig->alphaBits );
+ }
+
+ if( fbconfig->depthBits > 0)
+ {
+ ADD_ATTR2( NSOpenGLPFADepthSize, fbconfig->depthBits );
+ }
+
+ if( fbconfig->stencilBits > 0)
+ {
+ ADD_ATTR2( NSOpenGLPFAStencilSize, fbconfig->stencilBits );
+ }
+
+ int accumBits = fbconfig->accumRedBits + fbconfig->accumGreenBits +
+ fbconfig->accumBlueBits + fbconfig->accumAlphaBits;
+
+ if( accumBits > 0)
+ {
+ ADD_ATTR2( NSOpenGLPFAAccumSize, accumBits );
+ }
+
+ if( fbconfig->auxBuffers > 0)
+ {
+ ADD_ATTR2( NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers );
+ }
+
+ if( fbconfig->stereo)
+ {
+ ADD_ATTR( NSOpenGLPFAStereo );
+ }
+
+ if( fbconfig->samples > 0)
+ {
+ ADD_ATTR2( NSOpenGLPFASampleBuffers, 1 );
+ ADD_ATTR2( NSOpenGLPFASamples, fbconfig->samples );
+ }
+
+ ADD_ATTR(0);
+
+ _glfwWin.pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
+ if( _glfwWin.pixelFormat == nil )
+ {
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ _glfwWin.context = [[NSOpenGLContext alloc] initWithFormat:_glfwWin.pixelFormat
+ shareContext:nil];
+ if( _glfwWin.context == nil )
+ {
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ [_glfwWin.window makeKeyAndOrderFront:nil];
+ [_glfwWin.context setView:[_glfwWin.window contentView]];
+
+ if( wndconfig->mode == GLFW_FULLSCREEN )
+ {
+ // TODO: Make this work on pre-Leopard systems
+ [[_glfwWin.window contentView] enterFullScreenMode:[NSScreen mainScreen]
+ withOptions:nil];
+ }
+
+ [_glfwWin.context makeCurrentContext];
+
+ NSPoint point = [[NSCursor currentCursor] hotSpot];
+ _glfwInput.MousePosX = point.x;
+ _glfwInput.MousePosY = point.y;
+
+ return GL_TRUE;
+}
+
+//========================================================================
+// Properly kill the window / video display
+//========================================================================
+
+void _glfwPlatformCloseWindow( void )
+{
+ [_glfwWin.window orderOut:nil];
+
+ if( _glfwWin.fullscreen )
+ {
+ [[_glfwWin.window contentView] exitFullScreenModeWithOptions:nil];
+ CGDisplaySwitchToMode( CGMainDisplayID(),
+ (CFDictionaryRef)_glfwLibrary.DesktopMode );
+ CGReleaseAllDisplays();
+ }
+
+ [_glfwWin.pixelFormat release];
+ _glfwWin.pixelFormat = nil;
+
+ [NSOpenGLContext clearCurrentContext];
+ [_glfwWin.context release];
+ _glfwWin.context = nil;
+
+ [_glfwWin.window setDelegate:nil];
+ [NSApp setDelegate:nil];
+ [_glfwWin.delegate release];
+ _glfwWin.delegate = nil;
+
+ [_glfwWin.window close];
+ _glfwWin.window = nil;
+
+ // TODO: Probably more cleanup
+}
+
+//========================================================================
+// Set the window title
+//========================================================================
+
+void _glfwPlatformSetWindowTitle( const char *title )
+{
+ [_glfwWin.window setTitle:[NSString stringWithCString:title
+ encoding:NSISOLatin1StringEncoding]];
+}
+
+//========================================================================
+// Set the window size
+//========================================================================
+
+void _glfwPlatformSetWindowSize( int width, int height )
+{
+ [_glfwWin.window setContentSize:NSMakeSize(width, height)];
+}
+
+//========================================================================
+// Set the window position
+//========================================================================
+
+void _glfwPlatformSetWindowPos( int x, int y )
+{
+ NSRect contentRect = [_glfwWin.window contentRectForFrameRect:[_glfwWin.window frame]];
+
+ // We assume here that the client code wants to position the window within the
+ // screen the window currently occupies
+ NSRect screenRect = [[_glfwWin.window screen] visibleFrame];
+ contentRect.origin = NSMakePoint(screenRect.origin.x + x,
+ screenRect.origin.y + screenRect.size.height -
+ y - contentRect.size.height);
+
+ [_glfwWin.window setFrame:[_glfwWin.window frameRectForContentRect:contentRect]
+ display:YES];
+}
+
+//========================================================================
+// Iconify the window
+//========================================================================
+
+void _glfwPlatformIconifyWindow( void )
+{
+ [_glfwWin.window miniaturize:nil];
+}
+
+//========================================================================
+// Restore (un-iconify) the window
+//========================================================================
+
+void _glfwPlatformRestoreWindow( void )
+{
+ [_glfwWin.window deminiaturize:nil];
+}
+
+//========================================================================
+// Swap buffers
+//========================================================================
+
+void _glfwPlatformSwapBuffers( void )
+{
+ // ARP appears to be unnecessary, but this is future-proof
+ [_glfwWin.context flushBuffer];
+}
+
+//========================================================================
+// Set double buffering swap interval
+//========================================================================
+
+void _glfwPlatformSwapInterval( int interval )
+{
+ GLint sync = interval;
+ [_glfwWin.context setValues:&sync forParameter:NSOpenGLCPSwapInterval];
+}
+
+//========================================================================
+// Write back window parameters into GLFW window structure
+//========================================================================
+
+void _glfwPlatformRefreshWindowParams( void )
+{
+ GLint value;
+
+ // Since GLFW 2.x doesn't understand screens, we use virtual screen zero
+
+ [_glfwWin.pixelFormat getValues:&value
+ forAttribute:NSOpenGLPFAAccelerated
+ forVirtualScreen:0];
+ _glfwWin.accelerated = value;
+
+ [_glfwWin.pixelFormat getValues:&value
+ forAttribute:NSOpenGLPFAAlphaSize
+ forVirtualScreen:0];
+ _glfwWin.alphaBits = value;
+
+ // It seems that the color size includes the size of the alpha channel
+ [_glfwWin.pixelFormat getValues:&value
+ forAttribute:NSOpenGLPFAColorSize
+ forVirtualScreen:0];
+ value -= _glfwWin.alphaBits;
+ _glfwWin.redBits = value / 3;
+ _glfwWin.greenBits = value / 3;
+ _glfwWin.blueBits = value / 3;
+
+ [_glfwWin.pixelFormat getValues:&value
+ forAttribute:NSOpenGLPFADepthSize
+ forVirtualScreen:0];
+ _glfwWin.depthBits = value;
+
+ [_glfwWin.pixelFormat getValues:&value
+ forAttribute:NSOpenGLPFAStencilSize
+ forVirtualScreen:0];
+ _glfwWin.stencilBits = value;
+
+ [_glfwWin.pixelFormat getValues:&value
+ forAttribute:NSOpenGLPFAAccumSize
+ forVirtualScreen:0];
+ _glfwWin.accumRedBits = value / 3;
+ _glfwWin.accumGreenBits = value / 3;
+ _glfwWin.accumBlueBits = value / 3;
+
+ // TODO: Figure out what to set this value to
+ _glfwWin.accumAlphaBits = 0;
+
+ [_glfwWin.pixelFormat getValues:&value
+ forAttribute:NSOpenGLPFAAuxBuffers
+ forVirtualScreen:0];
+ _glfwWin.auxBuffers = value;
+
+ [_glfwWin.pixelFormat getValues:&value
+ forAttribute:NSOpenGLPFAStereo
+ forVirtualScreen:0];
+ _glfwWin.stereo = value;
+
+ [_glfwWin.pixelFormat getValues:&value
+ forAttribute:NSOpenGLPFASamples
+ forVirtualScreen:0];
+ _glfwWin.samples = value;
+
+ // These are forced to false as long as Mac OS X lacks support for OpenGL 3.0+
+ _glfwWin.glForward = GL_FALSE;
+ _glfwWin.glDebug = GL_FALSE;
+ _glfwWin.glProfile = 0;
+}
+
+//========================================================================
+// Poll for new window and input events
+//========================================================================
+
+void _glfwPlatformPollEvents( void )
+{
+ NSEvent *event;
+
+ do
+ {
+ event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantPast]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+
+ if (event)
+ {
+ [NSApp sendEvent:event];
+ }
+ }
+ while (event);
+
+ [_glfwLibrary.AutoreleasePool drain];
+ _glfwLibrary.AutoreleasePool = [[NSAutoreleasePool alloc] init];
+}
+
+//========================================================================
+// Wait for new window and input events
+//========================================================================
+
+void _glfwPlatformWaitEvents( void )
+{
+ // I wanted to pass NO to dequeue:, and rely on PollEvents to
+ // dequeue and send. For reasons not at all clear to me, passing
+ // NO to dequeue: causes this method never to return.
+ NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantFuture]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ [NSApp sendEvent:event];
+
+ _glfwPlatformPollEvents();
+}
+
+//========================================================================
+// Hide mouse cursor (lock it)
+//========================================================================
+
+void _glfwPlatformHideMouseCursor( void )
+{
+ [NSCursor hide];
+ CGAssociateMouseAndMouseCursorPosition( false );
+}
+
+//========================================================================
+// Show mouse cursor (unlock it)
+//========================================================================
+
+void _glfwPlatformShowMouseCursor( void )
+{
+ [NSCursor unhide];
+ CGAssociateMouseAndMouseCursorPosition( true );
+}
+
+//========================================================================
+// Set physical mouse cursor position
+//========================================================================
+
+void _glfwPlatformSetMouseCursorPos( int x, int y )
+{
+ // The library seems to assume that after calling this the mouse won't move,
+ // but obviously it will, and escape the app's window, and activate other apps,
+ // and other badness in pain. I think the API's just silly, but maybe I'm
+ // misunderstanding it...
+
+ // Also, (x, y) are window coords...
+
+ // Also, it doesn't seem possible to write this robustly without
+ // calculating the maximum y coordinate of all screens, since Cocoa's
+ // "global coordinates" are upside down from CG's...
+
+ // Without this (once per app run, but it's convenient to do it here)
+ // events will be suppressed for a default of 0.25 seconds after we
+ // move the cursor.
+ CGSetLocalEventsSuppressionInterval( 0.0 );
+
+ NSPoint localPoint = NSMakePoint( x, y );
+ NSPoint globalPoint = [_glfwWin.window convertBaseToScreen:localPoint];
+ CGPoint mainScreenOrigin = CGDisplayBounds( CGMainDisplayID() ).origin;
+ double mainScreenHeight = CGDisplayBounds( CGMainDisplayID() ).size.height;
+ CGPoint targetPoint = CGPointMake( globalPoint.x - mainScreenOrigin.x,
+ mainScreenHeight - globalPoint.y - mainScreenOrigin.y );
+ CGDisplayMoveCursorToPoint( CGMainDisplayID(), targetPoint );
+}
+
diff --git a/lib/cocoa/libglfw.pc.cmake b/lib/cocoa/libglfw.pc.cmake
new file mode 100644
index 00000000..2700c59d
--- /dev/null
+++ b/lib/cocoa/libglfw.pc.cmake
@@ -0,0 +1,11 @@
+prefix=@PREFIX@
+exec_prefix=@PREFIX@
+libdir=@PREFIX@/lib
+includedir=@PREFIX@/include
+
+Name: GLFW
+Description: A portable framework for OpenGL development
+Version: 2.7
+URL: http://glfw.sourceforge.net/
+Libs: -L${libdir} -lglfw -framework AGL -framework OpenGL -framework Carbon
+Cflags: -I${includedir}
diff --git a/lib/cocoa/platform.h b/lib/cocoa/platform.h
new file mode 100644
index 00000000..844f0c4f
--- /dev/null
+++ b/lib/cocoa/platform.h
@@ -0,0 +1,189 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Cocoa/NSOpenGL
+// API Version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2010 Camilla Berglund
+//
+// 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 _platform_h_
+#define _platform_h_
+
+
+// This is the Mac OS X version of GLFW
+#define _GLFW_MAC_OS_X
+
+#if defined(__OBJC__)
+#import
+#else
+typedef void *id;
+#endif
+
+#include "../../include/GL/glfw.h"
+
+
+#ifndef GL_VERSION_3_0
+
+typedef const GLubyte * (APIENTRY *PFNGLGETSTRINGIPROC) (GLenum, GLuint);
+
+#endif /*GL_VERSION_3_0*/
+
+
+//========================================================================
+// GLFW platform specific types
+//========================================================================
+
+//------------------------------------------------------------------------
+// Pointer length integer
+//------------------------------------------------------------------------
+typedef intptr_t GLFWintptr;
+
+//------------------------------------------------------------------------
+// Window structure
+//------------------------------------------------------------------------
+typedef struct _GLFWwin_struct _GLFWwin;
+
+struct _GLFWwin_struct {
+
+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
+
+ // User callback functions
+ GLFWwindowsizefun windowSizeCallback;
+ GLFWwindowclosefun windowCloseCallback;
+ GLFWwindowrefreshfun windowRefreshCallback;
+ GLFWmousebuttonfun mouseButtonCallback;
+ GLFWmouseposfun mousePosCallback;
+ GLFWmousewheelfun mouseWheelCallback;
+ GLFWkeyfun keyCallback;
+ GLFWcharfun charCallback;
+
+ // User selected window settings
+ int fullscreen; // Fullscreen flag
+ int mouseLock; // Mouse-lock flag
+ int autoPollEvents; // Auto polling flag
+ int sysKeysDisabled; // System keys disabled flag
+ int windowNoResize; // Resize- and maximize gadgets disabled flag
+ int refreshRate; // Vertical monitor refresh rate
+
+ // Window status & parameters
+ int opened; // Flag telling if window is opened or not
+ int active; // Application active flag
+ int iconified; // Window iconified flag
+ int width, height; // Window width and heigth
+ int accelerated; // GL_TRUE if window is HW accelerated
+
+ // Framebuffer attributes
+ int redBits;
+ int greenBits;
+ int blueBits;
+ int alphaBits;
+ int depthBits;
+ int stencilBits;
+ int accumRedBits;
+ int accumGreenBits;
+ int accumBlueBits;
+ int accumAlphaBits;
+ int auxBuffers;
+ int stereo;
+ int samples;
+
+ // OpenGL extensions and context attributes
+ int has_GL_SGIS_generate_mipmap;
+ int has_GL_ARB_texture_non_power_of_two;
+ int glMajor, glMinor, glRevision;
+ int glForward, glDebug, glProfile;
+
+ PFNGLGETSTRINGIPROC GetStringi;
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+ id window;
+ id pixelFormat;
+ id context;
+ id delegate;
+ unsigned int modifierFlags;
+};
+
+GLFWGLOBAL _GLFWwin _glfwWin;
+
+
+//------------------------------------------------------------------------
+// Library global data
+//------------------------------------------------------------------------
+GLFWGLOBAL struct {
+
+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
+
+ // Window opening hints
+ _GLFWhints hints;
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+ // Timer data
+ struct {
+ double t0;
+ } Timer;
+
+ // dlopen handle for dynamically-loading extension function pointers
+ void *OpenGLFramework;
+
+ int Unbundled;
+
+ id DesktopMode;
+
+ id AutoreleasePool;
+
+} _glfwLibrary;
+
+
+//------------------------------------------------------------------------
+// User input status (some of this should go in _GLFWwin)
+//------------------------------------------------------------------------
+GLFWGLOBAL struct {
+
+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
+
+ // Mouse status
+ int MousePosX, MousePosY;
+ int WheelPos;
+ char MouseButton[ GLFW_MOUSE_BUTTON_LAST+1 ];
+
+ // Keyboard status
+ char Key[ GLFW_KEY_LAST+1 ];
+ int LastChar;
+
+ // User selected settings
+ int StickyKeys;
+ int StickyMouseButtons;
+ int KeyRepeat;
+
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+ double WheelPosFloating;
+
+} _glfwInput;
+
+
+#endif // _platform_h_
diff --git a/lib/enable.c b/lib/enable.c
new file mode 100644
index 00000000..afafd89f
--- /dev/null
+++ b/lib/enable.c
@@ -0,0 +1,310 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Any
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+//========================================================================
+// Enable (show) mouse cursor
+//========================================================================
+
+static void enableMouseCursor( void )
+{
+ int centerPosX, centerPosY;
+
+ if( !_glfwWin.opened || !_glfwWin.mouseLock )
+ {
+ return;
+ }
+
+ // Show mouse cursor
+ _glfwPlatformShowMouseCursor();
+
+ centerPosX = _glfwWin.width / 2;
+ centerPosY = _glfwWin.height / 2;
+
+ if( centerPosX != _glfwInput.MousePosX || centerPosY != _glfwInput.MousePosY )
+ {
+ _glfwPlatformSetMouseCursorPos( centerPosX, centerPosY );
+
+ _glfwInput.MousePosX = centerPosX;
+ _glfwInput.MousePosY = centerPosY;
+
+ if( _glfwWin.mousePosCallback )
+ {
+ _glfwWin.mousePosCallback( _glfwInput.MousePosX,
+ _glfwInput.MousePosY );
+ }
+ }
+
+ // From now on the mouse is unlocked
+ _glfwWin.mouseLock = GL_FALSE;
+}
+
+//========================================================================
+// Disable (hide) mouse cursor
+//========================================================================
+
+static void disableMouseCursor( void )
+{
+ if( !_glfwWin.opened || _glfwWin.mouseLock )
+ {
+ return;
+ }
+
+ // Hide mouse cursor
+ _glfwPlatformHideMouseCursor();
+
+ // Move cursor to the middle of the window
+ _glfwPlatformSetMouseCursorPos( _glfwWin.width >> 1,
+ _glfwWin.height >> 1 );
+
+ // From now on the mouse is locked
+ _glfwWin.mouseLock = GL_TRUE;
+}
+
+
+//========================================================================
+// Enable sticky keys
+//========================================================================
+
+static void enableStickyKeys( void )
+{
+ _glfwInput.StickyKeys = 1;
+}
+
+//========================================================================
+// Disable sticky keys
+//========================================================================
+
+static void disableStickyKeys( void )
+{
+ int i;
+
+ _glfwInput.StickyKeys = 0;
+
+ // Release all sticky keys
+ for( i = 0; i <= GLFW_KEY_LAST; i++ )
+ {
+ if( _glfwInput.Key[ i ] == 2 )
+ {
+ _glfwInput.Key[ i ] = 0;
+ }
+ }
+}
+
+
+//========================================================================
+// Enable sticky mouse buttons
+//========================================================================
+
+static void enableStickyMouseButtons( void )
+{
+ _glfwInput.StickyMouseButtons = 1;
+}
+
+//========================================================================
+// Disable sticky mouse buttons
+//========================================================================
+
+static void disableStickyMouseButtons( void )
+{
+ int i;
+
+ _glfwInput.StickyMouseButtons = 0;
+
+ // Release all sticky mouse buttons
+ for( i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++ )
+ {
+ if( _glfwInput.MouseButton[ i ] == 2 )
+ {
+ _glfwInput.MouseButton[ i ] = 0;
+ }
+ }
+}
+
+
+//========================================================================
+// Enable system keys
+//========================================================================
+
+static void enableSystemKeys( void )
+{
+ if( !_glfwWin.sysKeysDisabled )
+ {
+ return;
+ }
+
+ _glfwPlatformEnableSystemKeys();
+
+ // Indicate that system keys are no longer disabled
+ _glfwWin.sysKeysDisabled = GL_FALSE;
+}
+
+//========================================================================
+// Disable system keys
+//========================================================================
+
+static void disableSystemKeys( void )
+{
+ if( _glfwWin.sysKeysDisabled )
+ {
+ return;
+ }
+
+ _glfwPlatformDisableSystemKeys();
+
+ // Indicate that system keys are now disabled
+ _glfwWin.sysKeysDisabled = GL_TRUE;
+}
+
+
+//========================================================================
+// Enable key repeat
+//========================================================================
+
+static void enableKeyRepeat( void )
+{
+ _glfwInput.KeyRepeat = 1;
+}
+
+//========================================================================
+// Disable key repeat
+//========================================================================
+
+static void disableKeyRepeat( void )
+{
+ _glfwInput.KeyRepeat = 0;
+}
+
+
+//========================================================================
+// Enable automatic event polling
+//========================================================================
+
+static void enableAutoPollEvents( void )
+{
+ _glfwWin.autoPollEvents = 1;
+}
+
+//========================================================================
+// Disable automatic event polling
+//========================================================================
+
+static void disableAutoPollEvents( void )
+{
+ _glfwWin.autoPollEvents = 0;
+}
+
+
+
+//************************************************************************
+//**** GLFW user functions ****
+//************************************************************************
+
+//========================================================================
+// Enable certain GLFW/window/system functions.
+//========================================================================
+
+GLFWAPI void glfwEnable( int token )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized )
+ {
+ return;
+ }
+
+ switch( token )
+ {
+ case GLFW_MOUSE_CURSOR:
+ enableMouseCursor();
+ break;
+ case GLFW_STICKY_KEYS:
+ enableStickyKeys();
+ break;
+ case GLFW_STICKY_MOUSE_BUTTONS:
+ enableStickyMouseButtons();
+ break;
+ case GLFW_SYSTEM_KEYS:
+ enableSystemKeys();
+ break;
+ case GLFW_KEY_REPEAT:
+ enableKeyRepeat();
+ break;
+ case GLFW_AUTO_POLL_EVENTS:
+ enableAutoPollEvents();
+ break;
+ default:
+ break;
+ }
+}
+
+
+//========================================================================
+// Disable certain GLFW/window/system functions.
+//========================================================================
+
+GLFWAPI void glfwDisable( int token )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized )
+ {
+ return;
+ }
+
+ switch( token )
+ {
+ case GLFW_MOUSE_CURSOR:
+ disableMouseCursor();
+ break;
+ case GLFW_STICKY_KEYS:
+ disableStickyKeys();
+ break;
+ case GLFW_STICKY_MOUSE_BUTTONS:
+ disableStickyMouseButtons();
+ break;
+ case GLFW_SYSTEM_KEYS:
+ disableSystemKeys();
+ break;
+ case GLFW_KEY_REPEAT:
+ disableKeyRepeat();
+ break;
+ case GLFW_AUTO_POLL_EVENTS:
+ disableAutoPollEvents();
+ break;
+ default:
+ break;
+ }
+}
+
diff --git a/lib/fullscreen.c b/lib/fullscreen.c
new file mode 100644
index 00000000..0e363cc6
--- /dev/null
+++ b/lib/fullscreen.c
@@ -0,0 +1,94 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Any
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+//************************************************************************
+//**** GLFW user functions ****
+//************************************************************************
+
+//========================================================================
+// glfwGetVideoModes() - Get a list of available video modes
+//========================================================================
+
+GLFWAPI int glfwGetVideoModes( GLFWvidmode *list, int maxcount )
+{
+ int count, i, swap, res1, res2, depth1, depth2;
+ GLFWvidmode vm;
+
+ if( !_glfwInitialized || maxcount <= 0 || list == (GLFWvidmode*) 0 )
+ {
+ return 0;
+ }
+
+ // Get list of video modes
+ count = _glfwPlatformGetVideoModes( list, maxcount );
+
+ // Sort list (bubble sort)
+ do
+ {
+ swap = 0;
+ for( i = 0; i < count-1; ++ i )
+ {
+ res1 = list[i].Width*list[i].Height;
+ depth1 = list[i].RedBits+list[i].GreenBits+list[i].BlueBits;
+ res2 = list[i+1].Width*list[i+1].Height;
+ depth2 = list[i+1].RedBits+list[i+1].GreenBits+
+ list[i+1].BlueBits;
+ if( (depth2
+//
+// 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"
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+#ifndef GL_VERSION_3_0
+#define GL_NUM_EXTENSIONS 0x821D
+#endif
+
+//========================================================================
+// Parses the OpenGL version string and extracts the version number
+//========================================================================
+
+void _glfwParseGLVersion( int *major, int *minor, int *rev )
+{
+ GLuint _major, _minor = 0, _rev = 0;
+ const GLubyte *version;
+ const GLubyte *ptr;
+
+ // Get OpenGL version string
+ version = glGetString( GL_VERSION );
+ if( !version )
+ {
+ return;
+ }
+
+ // Parse string
+ ptr = version;
+ for( _major = 0; *ptr >= '0' && *ptr <= '9'; ptr ++ )
+ {
+ _major = 10*_major + (*ptr - '0');
+ }
+ if( *ptr == '.' )
+ {
+ ptr ++;
+ for( _minor = 0; *ptr >= '0' && *ptr <= '9'; ptr ++ )
+ {
+ _minor = 10*_minor + (*ptr - '0');
+ }
+ if( *ptr == '.' )
+ {
+ ptr ++;
+ for( _rev = 0; *ptr >= '0' && *ptr <= '9'; ptr ++ )
+ {
+ _rev = 10*_rev + (*ptr - '0');
+ }
+ }
+ }
+
+ // Return parsed values
+ *major = _major;
+ *minor = _minor;
+ *rev = _rev;
+}
+
+//========================================================================
+// _glfwStringInExtensionString() - Check if a string can be found in an
+// OpenGL extension string
+//========================================================================
+
+int _glfwStringInExtensionString( const char *string,
+ const GLubyte *extensions )
+{
+ const GLubyte *start;
+ GLubyte *where, *terminator;
+
+ // It takes a bit of care to be fool-proof about parsing the
+ // OpenGL extensions string. Don't be fooled by sub-strings,
+ // etc.
+ start = extensions;
+ while( 1 )
+ {
+ where = (GLubyte *) strstr( (const char *) start, string );
+ if( !where )
+ {
+ return GL_FALSE;
+ }
+ terminator = where + strlen( string );
+ if( where == start || *(where - 1) == ' ' )
+ {
+ if( *terminator == ' ' || *terminator == '\0' )
+ {
+ break;
+ }
+ }
+ start = terminator;
+ }
+
+ return GL_TRUE;
+}
+
+
+
+//************************************************************************
+//**** GLFW user functions ****
+//************************************************************************
+
+//========================================================================
+// Check if an OpenGL extension is available at runtime
+//========================================================================
+
+GLFWAPI int glfwExtensionSupported( const char *extension )
+{
+ const GLubyte *extensions;
+ GLubyte *where;
+ GLint count;
+ int i;
+
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return GL_FALSE;
+ }
+
+ // Extension names should not have spaces
+ where = (GLubyte *) strchr( extension, ' ' );
+ if( where || *extension == '\0' )
+ {
+ return GL_FALSE;
+ }
+
+ if( _glfwWin.glMajor < 3 )
+ {
+ // Check if extension is in the old style OpenGL extensions string
+
+ extensions = glGetString( GL_EXTENSIONS );
+ if( extensions != NULL )
+ {
+ if( _glfwStringInExtensionString( extension, extensions ) )
+ {
+ return GL_TRUE;
+ }
+ }
+ }
+ else
+ {
+ // Check if extension is in the modern OpenGL extensions string list
+
+ glGetIntegerv( GL_NUM_EXTENSIONS, &count );
+
+ for( i = 0; i < count; i++ )
+ {
+ if( strcmp( (const char*) _glfwWin.GetStringi( GL_EXTENSIONS, i ),
+ extension ) == 0 )
+ {
+ return GL_TRUE;
+ }
+ }
+ }
+
+ // Additional platform specific extension checking (e.g. WGL)
+ if( _glfwPlatformExtensionSupported( extension ) )
+ {
+ return GL_TRUE;
+ }
+
+ return GL_FALSE;
+}
+
+
+//========================================================================
+// glfwGetProcAddress() - Get the function pointer to an OpenGL function.
+// This function can be used to get access to extended OpenGL functions.
+//========================================================================
+
+GLFWAPI void * glfwGetProcAddress( const char *procname )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return NULL;
+ }
+
+ return _glfwPlatformGetProcAddress( procname );
+}
+
+
+//========================================================================
+// Returns the OpenGL version
+//========================================================================
+
+GLFWAPI void glfwGetGLVersion( int *major, int *minor, int *rev )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ if( major != NULL )
+ {
+ *major = _glfwWin.glMajor;
+ }
+ if( minor != NULL )
+ {
+ *minor = _glfwWin.glMinor;
+ }
+ if( rev != NULL )
+ {
+ *rev = _glfwWin.glRevision;
+ }
+}
+
diff --git a/lib/init.c b/lib/init.c
new file mode 100644
index 00000000..f3d3dee7
--- /dev/null
+++ b/lib/init.c
@@ -0,0 +1,110 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Any
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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.
+//
+//========================================================================
+
+#define _init_c_
+#include "internal.h"
+
+
+//************************************************************************
+//**** GLFW user functions ****
+//************************************************************************
+
+//========================================================================
+// glfwInit() - Initialize various GLFW state
+//========================================================================
+
+GLFWAPI int glfwInit( void )
+{
+ // Is GLFW already initialized?
+ if( _glfwInitialized )
+ {
+ return GL_TRUE;
+ }
+
+ memset( &_glfwLibrary, 0, sizeof( _glfwLibrary ) );
+ memset( &_glfwWin, 0, sizeof( _glfwWin ) );
+
+ // Window is not yet opened
+ _glfwWin.opened = GL_FALSE;
+
+ // Default enable/disable settings
+ _glfwWin.sysKeysDisabled = GL_FALSE;
+
+ // Clear window hints
+ _glfwClearWindowHints();
+
+ // Platform specific initialization
+ if( !_glfwPlatformInit() )
+ {
+ return GL_FALSE;
+ }
+
+ // Form now on, GLFW state is valid
+ _glfwInitialized = GL_TRUE;
+
+ return GL_TRUE;
+}
+
+
+
+//========================================================================
+// Close window and shut down library
+//========================================================================
+
+GLFWAPI void glfwTerminate( void )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized )
+ {
+ return;
+ }
+
+ // Platform specific termination
+ if( !_glfwPlatformTerminate() )
+ {
+ return;
+ }
+
+ // GLFW is no longer initialized
+ _glfwInitialized = GL_FALSE;
+}
+
+
+//========================================================================
+// glfwGetVersion() - Get GLFW version
+//========================================================================
+
+GLFWAPI void glfwGetVersion( int *major, int *minor, int *rev )
+{
+ if( major != NULL ) *major = GLFW_VERSION_MAJOR;
+ if( minor != NULL ) *minor = GLFW_VERSION_MINOR;
+ if( rev != NULL ) *rev = GLFW_VERSION_REVISION;
+}
+
diff --git a/lib/input.c b/lib/input.c
new file mode 100644
index 00000000..faf47cc2
--- /dev/null
+++ b/lib/input.c
@@ -0,0 +1,280 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Any
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+//========================================================================
+// glfwGetKey()
+//========================================================================
+
+GLFWAPI int glfwGetKey( int key )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return GLFW_RELEASE;
+ }
+
+ // Is it a valid key?
+ if( key < 0 || key > GLFW_KEY_LAST )
+ {
+ return GLFW_RELEASE;
+ }
+
+ if( _glfwInput.Key[ key ] == GLFW_STICK )
+ {
+ // Sticky mode: release key now
+ _glfwInput.Key[ key ] = GLFW_RELEASE;
+ return GLFW_PRESS;
+ }
+
+ return (int) _glfwInput.Key[ key ];
+}
+
+
+//========================================================================
+// glfwGetMouseButton()
+//========================================================================
+
+GLFWAPI int glfwGetMouseButton( int button )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return GLFW_RELEASE;
+ }
+
+ // Is it a valid mouse button?
+ if( button < 0 || button > GLFW_MOUSE_BUTTON_LAST )
+ {
+ return GLFW_RELEASE;
+ }
+
+ if( _glfwInput.MouseButton[ button ] == GLFW_STICK )
+ {
+ // Sticky mode: release mouse button now
+ _glfwInput.MouseButton[ button ] = GLFW_RELEASE;
+ return GLFW_PRESS;
+ }
+
+ return (int) _glfwInput.MouseButton[ button ];
+}
+
+
+//========================================================================
+// glfwGetMousePos()
+//========================================================================
+
+GLFWAPI void glfwGetMousePos( int *xpos, int *ypos )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Return mouse position
+ if( xpos != NULL )
+ {
+ *xpos = _glfwInput.MousePosX;
+ }
+ if( ypos != NULL )
+ {
+ *ypos = _glfwInput.MousePosY;
+ }
+}
+
+
+//========================================================================
+// glfwSetMousePos()
+//========================================================================
+
+GLFWAPI void glfwSetMousePos( int xpos, int ypos )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Don't do anything if the mouse position did not change
+ if( xpos == _glfwInput.MousePosX && ypos == _glfwInput.MousePosY )
+ {
+ return;
+ }
+
+ // Set GLFW mouse position
+ _glfwInput.MousePosX = xpos;
+ _glfwInput.MousePosY = ypos;
+
+ // If we have a locked mouse, do not change cursor position
+ if( _glfwWin.mouseLock )
+ {
+ return;
+ }
+
+ // Update physical cursor position
+ _glfwPlatformSetMouseCursorPos( xpos, ypos );
+}
+
+
+//========================================================================
+// glfwGetMouseWheel()
+//========================================================================
+
+GLFWAPI int glfwGetMouseWheel( void )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return 0;
+ }
+
+ // Return mouse wheel position
+ return _glfwInput.WheelPos;
+}
+
+
+//========================================================================
+// glfwSetMouseWheel()
+//========================================================================
+
+GLFWAPI void glfwSetMouseWheel( int pos )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Set mouse wheel position
+ _glfwInput.WheelPos = pos;
+}
+
+
+//========================================================================
+// glfwSetKeyCallback() - Set callback function for keyboard input
+//========================================================================
+
+GLFWAPI void glfwSetKeyCallback( GLFWkeyfun cbfun )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Set callback function
+ _glfwWin.keyCallback = cbfun;
+}
+
+
+//========================================================================
+// glfwSetCharCallback() - Set callback function for character input
+//========================================================================
+
+GLFWAPI void glfwSetCharCallback( GLFWcharfun cbfun )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Set callback function
+ _glfwWin.charCallback = cbfun;
+}
+
+
+//========================================================================
+// glfwSetMouseButtonCallback() - Set callback function for mouse clicks
+//========================================================================
+
+GLFWAPI void glfwSetMouseButtonCallback( GLFWmousebuttonfun cbfun )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Set callback function
+ _glfwWin.mouseButtonCallback = cbfun;
+}
+
+
+//========================================================================
+// glfwSetMousePosCallback() - Set callback function for mouse moves
+//========================================================================
+
+GLFWAPI void glfwSetMousePosCallback( GLFWmouseposfun cbfun )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Set callback function
+ _glfwWin.mousePosCallback = cbfun;
+
+ // Call the callback function to let the application know the current
+ // mouse position
+ if( cbfun )
+ {
+ cbfun( _glfwInput.MousePosX, _glfwInput.MousePosY );
+ }
+}
+
+
+//========================================================================
+// glfwSetMouseWheelCallback() - Set callback function for mouse wheel
+//========================================================================
+
+GLFWAPI void glfwSetMouseWheelCallback( GLFWmousewheelfun cbfun )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Set callback function
+ _glfwWin.mouseWheelCallback = cbfun;
+
+ // Call the callback function to let the application know the current
+ // mouse wheel position
+ if( cbfun )
+ {
+ cbfun( _glfwInput.WheelPos );
+ }
+}
+
diff --git a/lib/internal.h b/lib/internal.h
new file mode 100644
index 00000000..3aeb081a
--- /dev/null
+++ b/lib/internal.h
@@ -0,0 +1,221 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Any
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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 _internal_h_
+#define _internal_h_
+
+//========================================================================
+// GLFWGLOBAL is a macro that places all global variables in the init.c
+// module (all other modules reference global variables as 'extern')
+//========================================================================
+
+#if defined( _init_c_ )
+#define GLFWGLOBAL
+#else
+#define GLFWGLOBAL extern
+#endif
+
+
+//========================================================================
+// Input handling definitions
+//========================================================================
+
+// Internal key and button state/action definitions
+#define GLFW_STICK 2
+
+
+//========================================================================
+// System independent include files
+//========================================================================
+
+#include
+#include
+#include
+
+
+//------------------------------------------------------------------------
+// Window opening hints (set by glfwOpenWindowHint)
+// A bucket of semi-random stuff bunched together for historical reasons
+// This is used only by the platform independent code and only to store
+// parameters passed to us by glfwOpenWindowHint
+//------------------------------------------------------------------------
+typedef struct {
+ int refreshRate;
+ int accumRedBits;
+ int accumGreenBits;
+ int accumBlueBits;
+ int accumAlphaBits;
+ int auxBuffers;
+ int stereo;
+ int windowNoResize;
+ int samples;
+ int glMajor;
+ int glMinor;
+ int glForward;
+ int glDebug;
+ int glProfile;
+} _GLFWhints;
+
+
+//------------------------------------------------------------------------
+// Platform specific definitions goes in platform.h (which also includes
+// glfw.h)
+//------------------------------------------------------------------------
+
+#include "platform.h"
+
+
+//------------------------------------------------------------------------
+// Parameters relating to the creation of the context and window but not
+// directly related to the properties of the framebuffer
+// This is used to pass window and context creation parameters from the
+// platform independent code to the platform specific code
+//------------------------------------------------------------------------
+typedef struct {
+ int mode;
+ int refreshRate;
+ int windowNoResize;
+ int glMajor;
+ int glMinor;
+ int glForward;
+ int glDebug;
+ int glProfile;
+} _GLFWwndconfig;
+
+
+//------------------------------------------------------------------------
+// Framebuffer configuration descriptor, i.e. buffers and their sizes
+// Also a platform specific ID used to map back to the actual backend APIs
+// This is used to pass framebuffer parameters from the platform independent
+// code to the platform specific code, and also to enumerate and select
+// available framebuffer configurations
+//------------------------------------------------------------------------
+typedef struct {
+ int redBits;
+ int greenBits;
+ int blueBits;
+ int alphaBits;
+ int depthBits;
+ int stencilBits;
+ int accumRedBits;
+ int accumGreenBits;
+ int accumBlueBits;
+ int accumAlphaBits;
+ int auxBuffers;
+ int stereo;
+ int samples;
+ GLFWintptr platformID;
+} _GLFWfbconfig;
+
+
+//========================================================================
+// System independent global variables (GLFW internals)
+//========================================================================
+
+// Flag indicating if GLFW has been initialized
+#if defined( _init_c_ )
+int _glfwInitialized = 0;
+#else
+GLFWGLOBAL int _glfwInitialized;
+#endif
+
+
+//========================================================================
+// Prototypes for platform specific implementation functions
+//========================================================================
+
+// Init/terminate
+int _glfwPlatformInit( void );
+int _glfwPlatformTerminate( void );
+
+// Enable/Disable
+void _glfwPlatformEnableSystemKeys( void );
+void _glfwPlatformDisableSystemKeys( void );
+
+// Fullscreen
+int _glfwPlatformGetVideoModes( GLFWvidmode *list, int maxcount );
+void _glfwPlatformGetDesktopMode( GLFWvidmode *mode );
+
+// OpenGL extensions
+int _glfwPlatformExtensionSupported( const char *extension );
+void * _glfwPlatformGetProcAddress( const char *procname );
+
+// Joystick
+int _glfwPlatformGetJoystickParam( int joy, int param );
+int _glfwPlatformGetJoystickPos( int joy, float *pos, int numaxes );
+int _glfwPlatformGetJoystickButtons( int joy, unsigned char *buttons, int numbuttons );
+
+// Time
+double _glfwPlatformGetTime( void );
+void _glfwPlatformSetTime( double time );
+
+// Window management
+int _glfwPlatformOpenWindow( int width, int height, const _GLFWwndconfig *wndconfig, const _GLFWfbconfig *fbconfig );
+void _glfwPlatformCloseWindow( void );
+void _glfwPlatformSetWindowTitle( const char *title );
+void _glfwPlatformSetWindowSize( int width, int height );
+void _glfwPlatformSetWindowPos( int x, int y );
+void _glfwPlatformIconifyWindow( void );
+void _glfwPlatformRestoreWindow( void );
+void _glfwPlatformSwapBuffers( void );
+void _glfwPlatformSwapInterval( int interval );
+void _glfwPlatformRefreshWindowParams( void );
+void _glfwPlatformPollEvents( void );
+void _glfwPlatformWaitEvents( void );
+void _glfwPlatformHideMouseCursor( void );
+void _glfwPlatformShowMouseCursor( void );
+void _glfwPlatformSetMouseCursorPos( int x, int y );
+
+
+//========================================================================
+// Prototypes for platform independent internal functions
+//========================================================================
+
+// Window management (window.c)
+void _glfwClearWindowHints( void );
+
+// Input handling (window.c)
+void _glfwClearInput( void );
+void _glfwInputDeactivation( void );
+void _glfwInputKey( int key, int action );
+void _glfwInputChar( int character, int action );
+void _glfwInputMouseClick( int button, int action );
+
+// OpenGL extensions (glext.c)
+void _glfwParseGLVersion( int *major, int *minor, int *rev );
+int _glfwStringInExtensionString( const char *string, const GLubyte *extensions );
+
+// Framebuffer configs
+const _GLFWfbconfig *_glfwChooseFBConfig( const _GLFWfbconfig *desired,
+ const _GLFWfbconfig *alternatives,
+ unsigned int count );
+
+
+#endif // _internal_h_
diff --git a/lib/joystick.c b/lib/joystick.c
new file mode 100644
index 00000000..32841a75
--- /dev/null
+++ b/lib/joystick.c
@@ -0,0 +1,102 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Any
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+//************************************************************************
+//**** GLFW user functions ****
+//************************************************************************
+
+//========================================================================
+// glfwGetJoystickParam() - Determine joystick capabilities
+//========================================================================
+
+GLFWAPI int glfwGetJoystickParam( int joy, int param )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized )
+ {
+ return 0;
+ }
+
+ return _glfwPlatformGetJoystickParam( joy, param );
+}
+
+
+//========================================================================
+// glfwGetJoystickPos() - Get joystick axis positions
+//========================================================================
+
+GLFWAPI int glfwGetJoystickPos( int joy, float *pos, int numaxes )
+{
+ int i;
+
+ // Is GLFW initialized?
+ if( !_glfwInitialized )
+ {
+ return 0;
+ }
+
+ // Clear positions
+ for( i = 0; i < numaxes; i++ )
+ {
+ pos[ i ] = 0.0f;
+ }
+
+ return _glfwPlatformGetJoystickPos( joy, pos, numaxes );
+}
+
+
+//========================================================================
+// glfwGetJoystickButtons() - Get joystick button states
+//========================================================================
+
+GLFWAPI int glfwGetJoystickButtons( int joy,
+ unsigned char *buttons,
+ int numbuttons )
+{
+ int i;
+
+ // Is GLFW initialized?
+ if( !_glfwInitialized )
+ {
+ return 0;
+ }
+
+ // Clear button states
+ for( i = 0; i < numbuttons; i++ )
+ {
+ buttons[ i ] = GLFW_RELEASE;
+ }
+
+ return _glfwPlatformGetJoystickButtons( joy, buttons, numbuttons );
+}
+
diff --git a/lib/time.c b/lib/time.c
new file mode 100644
index 00000000..f7ea31c5
--- /dev/null
+++ b/lib/time.c
@@ -0,0 +1,68 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Any
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+//************************************************************************
+//**** GLFW user functions ****
+//************************************************************************
+
+//========================================================================
+// glfwGetTime() - Return timer value in seconds
+//========================================================================
+
+GLFWAPI double glfwGetTime( void )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized )
+ {
+ return 0.0;
+ }
+
+ return _glfwPlatformGetTime();
+}
+
+
+//========================================================================
+// glfwSetTime() - Set timer value in seconds
+//========================================================================
+
+GLFWAPI void glfwSetTime( double time )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized )
+ {
+ return;
+ }
+
+ _glfwPlatformSetTime( time );
+}
+
diff --git a/lib/win32/CMakeLists.txt b/lib/win32/CMakeLists.txt
new file mode 100644
index 00000000..d5230c68
--- /dev/null
+++ b/lib/win32/CMakeLists.txt
@@ -0,0 +1,55 @@
+
+if(CYGWIN)
+ configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/libglfw.pc.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/libglfw.pc @ONLY)
+
+# These lines are intended to remove the --export-all-symbols
+# flag added in the Modules/Platform/CYGWIN.cmake file of the
+# CMake distribution.
+# This is a HACK. If you have trouble _linking_ the GLFW
+# _shared_ library on Cygwin, try disabling this.
+ set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-shared")
+ set(CMAKE_SHARED_MODULE_CREATE_C_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS})
+
+endif(CYGWIN)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/lib)
+
+set(libglfw_SOURCES
+ ${common_SOURCES}
+ win32_enable.c
+ win32_fullscreen.c
+ win32_glext.c
+ win32_init.c
+ win32_joystick.c
+ win32_time.c
+ win32_window.c
+ win32_dllmain.c)
+
+add_library(libglfwStatic STATIC ${libglfw_SOURCES})
+add_library(libglfwShared SHARED glfwdll.def ${libglfw_SOURCES})
+
+target_link_libraries(libglfwShared ${OPENGL_gl_LIBRARY})
+set_target_properties(libglfwShared PROPERTIES
+ DEFINE_SYMBOL GLFW_BUILD_DLL
+ PREFIX ""
+ IMPORT_PREFIX ""
+ IMPORT_SUFFIX "dll.lib")
+
+set_target_properties(libglfwStatic libglfwShared PROPERTIES
+ CLEAN_DIRECT_OUTPUT 1
+ OUTPUT_NAME glfw)
+
+if(CYGWIN)
+ # Build for the regular Win32 environment (not Cygwin)
+ set_target_properties(libglfwStatic libglfwShared PROPERTIES COMPILE_FLAGS "-mwin32 -mno-cygwin")
+ set_target_properties(libglfwStatic libglfwShared PROPERTIES LINK_FLAGS "-mwin32 -mno-cygwin")
+endif(CYGWIN)
+
+install(TARGETS libglfwStatic libglfwShared DESTINATION lib)
+
+if(CYGWIN)
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libglfw.pc DESTINATION lib/pkgconfig)
+endif(CYGWIN)
+
diff --git a/lib/win32/glfwdll.def b/lib/win32/glfwdll.def
new file mode 100644
index 00000000..4f4ce470
--- /dev/null
+++ b/lib/win32/glfwdll.def
@@ -0,0 +1,46 @@
+LIBRARY GLFW.DLL
+
+EXPORTS
+glfwCloseWindow
+glfwDisable
+glfwEnable
+glfwExtensionSupported
+glfwGetDesktopMode
+glfwGetGLVersion
+glfwGetJoystickButtons
+glfwGetJoystickParam
+glfwGetJoystickPos
+glfwGetKey
+glfwGetMouseButton
+glfwGetMousePos
+glfwGetMouseWheel
+glfwGetProcAddress
+glfwGetTime
+glfwGetVersion
+glfwGetVideoModes
+glfwGetWindowParam
+glfwGetWindowSize
+glfwIconifyWindow
+glfwInit
+glfwOpenWindow
+glfwOpenWindowHint
+glfwPollEvents
+glfwRestoreWindow
+glfwSetCharCallback
+glfwSetKeyCallback
+glfwSetMouseButtonCallback
+glfwSetMousePos
+glfwSetMousePosCallback
+glfwSetMouseWheel
+glfwSetMouseWheelCallback
+glfwSetTime
+glfwSetWindowCloseCallback
+glfwSetWindowRefreshCallback
+glfwSetWindowPos
+glfwSetWindowSize
+glfwSetWindowSizeCallback
+glfwSetWindowTitle
+glfwSwapBuffers
+glfwSwapInterval
+glfwTerminate
+glfwWaitEvents
diff --git a/lib/win32/glfwdll_mgw1.def b/lib/win32/glfwdll_mgw1.def
new file mode 100644
index 00000000..bdf475f2
--- /dev/null
+++ b/lib/win32/glfwdll_mgw1.def
@@ -0,0 +1,46 @@
+LIBRARY GLFW.DLL
+
+EXPORTS
+glfwCloseWindow = glfwCloseWindow@0
+glfwDisable = glfwDisable@4
+glfwEnable = glfwEnable@4
+glfwExtensionSupported = glfwExtensionSupported@4
+glfwGetDesktopMode = glfwGetDesktopMode@4
+glfwGetGLVersion = glfwGetGLVersion@12
+glfwGetJoystickButtons = glfwGetJoystickButtons@12
+glfwGetJoystickParam = glfwGetJoystickParam@8
+glfwGetJoystickPos = glfwGetJoystickPos@12
+glfwGetKey = glfwGetKey@4
+glfwGetMouseButton = glfwGetMouseButton@4
+glfwGetMousePos = glfwGetMousePos@8
+glfwGetMouseWheel = glfwGetMouseWheel@0
+glfwGetProcAddress = glfwGetProcAddress@4
+glfwGetTime = glfwGetTime@0
+glfwGetVersion = glfwGetVersion@12
+glfwGetVideoModes = glfwGetVideoModes@8
+glfwGetWindowParam = glfwGetWindowParam@4
+glfwGetWindowSize = glfwGetWindowSize@8
+glfwIconifyWindow = glfwIconifyWindow@0
+glfwInit = glfwInit@0
+glfwOpenWindow = glfwOpenWindow@36
+glfwOpenWindowHint = glfwOpenWindowHint@8
+glfwPollEvents = glfwPollEvents@0
+glfwRestoreWindow = glfwRestoreWindow@0
+glfwSetCharCallback = glfwSetCharCallback@4
+glfwSetKeyCallback = glfwSetKeyCallback@4
+glfwSetMouseButtonCallback = glfwSetMouseButtonCallback@4
+glfwSetMousePos = glfwSetMousePos@8
+glfwSetMousePosCallback = glfwSetMousePosCallback@4
+glfwSetMouseWheel = glfwSetMouseWheel@4
+glfwSetMouseWheelCallback = glfwSetMouseWheelCallback@4
+glfwSetTime = glfwSetTime@8
+glfwSetWindowCloseCallback = glfwSetWindowCloseCallback@4
+glfwSetWindowRefreshCallback = glfwSetWindowRefreshCallback@4
+glfwSetWindowPos = glfwSetWindowPos@8
+glfwSetWindowSize = glfwSetWindowSize@8
+glfwSetWindowSizeCallback = glfwSetWindowSizeCallback@4
+glfwSetWindowTitle = glfwSetWindowTitle@4
+glfwSwapBuffers = glfwSwapBuffers@0
+glfwSwapInterval = glfwSwapInterval@4
+glfwTerminate = glfwTerminate@0
+glfwWaitEvents = glfwWaitEvents@0
diff --git a/lib/win32/glfwdll_mgw2.def b/lib/win32/glfwdll_mgw2.def
new file mode 100644
index 00000000..2a2b6ce1
--- /dev/null
+++ b/lib/win32/glfwdll_mgw2.def
@@ -0,0 +1,46 @@
+LIBRARY GLFW.DLL
+
+EXPORTS
+glfwCloseWindow@0
+glfwDisable@4
+glfwEnable@4
+glfwExtensionSupported@4
+glfwGetDesktopMode@4
+glfwGetGLVersion@12
+glfwGetJoystickButtons@12
+glfwGetJoystickParam@8
+glfwGetJoystickPos@12
+glfwGetKey@4
+glfwGetMouseButton@4
+glfwGetMousePos@8
+glfwGetMouseWheel@0
+glfwGetProcAddress@4
+glfwGetTime@0
+glfwGetVersion@12
+glfwGetVideoModes@8
+glfwGetWindowParam@4
+glfwGetWindowSize@8
+glfwIconifyWindow@0
+glfwInit@0
+glfwOpenWindow@36
+glfwOpenWindowHint@8
+glfwPollEvents@0
+glfwRestoreWindow@0
+glfwSetCharCallback@4
+glfwSetKeyCallback@4
+glfwSetMouseButtonCallback@4
+glfwSetMousePos@8
+glfwSetMousePosCallback@4
+glfwSetMouseWheel@4
+glfwSetMouseWheelCallback@4
+glfwSetTime@8
+glfwSetWindowCloseCallback@4
+glfwSetWindowRefreshCallback@4
+glfwSetWindowPos@8
+glfwSetWindowSize@8
+glfwSetWindowSizeCallback@4
+glfwSetWindowTitle@4
+glfwSwapBuffers@0
+glfwSwapInterval@4
+glfwTerminate@0
+glfwWaitEvents@0
diff --git a/lib/win32/libglfw.pc.cmake b/lib/win32/libglfw.pc.cmake
new file mode 100644
index 00000000..684b4ba2
--- /dev/null
+++ b/lib/win32/libglfw.pc.cmake
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: GLFW
+Description: A portable framework for OpenGL development
+Version: 2.7
+URL: http://glfw.sourceforge.net/
+Libs: -L${libdir} -lglfw @GLFW_LIBRARIES@
+Cflags: -I${includedir} -mwin32
diff --git a/lib/win32/platform.h b/lib/win32/platform.h
new file mode 100644
index 00000000..46cef336
--- /dev/null
+++ b/lib/win32/platform.h
@@ -0,0 +1,480 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Win32/WGL
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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 _platform_h_
+#define _platform_h_
+
+
+// This is the Windows version of GLFW
+#define _GLFW_WIN32
+
+// We don't need all the fancy stuff
+#define NOMINMAX
+#define WIN32_LEAN_AND_MEAN
+#define VC_EXTRALEAN
+
+// Include files
+#include
+#include
+#include "../../include/GL/glfw.h"
+
+
+//========================================================================
+// Hack: Define things that some 's do not define
+//========================================================================
+
+// Some old versions of w32api (used by MinGW and Cygwin) define
+// WH_KEYBOARD_LL without typedef:ing KBDLLHOOKSTRUCT (!)
+#if defined(__MINGW32__) || defined(__CYGWIN__)
+#include
+#if defined(WH_KEYBOARD_LL) && (__W32API_MAJOR_VERSION == 1) && (__W32API_MINOR_VERSION <= 2)
+#undef WH_KEYBOARD_LL
+#endif
+#endif
+
+//------------------------------------------------------------------------
+// ** NOTE ** If this gives you compiler errors and you are using MinGW
+// (or Dev-C++), update to w32api version 1.3 or later:
+// http://sourceforge.net/project/showfiles.php?group_id=2435
+//------------------------------------------------------------------------
+#ifndef WH_KEYBOARD_LL
+#define WH_KEYBOARD_LL 13
+typedef struct tagKBDLLHOOKSTRUCT {
+ DWORD vkCode;
+ DWORD scanCode;
+ DWORD flags;
+ DWORD time;
+ DWORD dwExtraInfo;
+} KBDLLHOOKSTRUCT, FAR *LPKBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;
+#endif // WH_KEYBOARD_LL
+
+#ifndef LLKHF_ALTDOWN
+#define LLKHF_ALTDOWN 0x00000020
+#endif
+
+#ifndef SPI_SETSCREENSAVERRUNNING
+#define SPI_SETSCREENSAVERRUNNING 97
+#endif
+#ifndef SPI_GETANIMATION
+#define SPI_GETANIMATION 72
+#endif
+#ifndef SPI_SETANIMATION
+#define SPI_SETANIMATION 73
+#endif
+#ifndef SPI_GETFOREGROUNDLOCKTIMEOUT
+#define SPI_GETFOREGROUNDLOCKTIMEOUT 0x2000
+#endif
+#ifndef SPI_SETFOREGROUNDLOCKTIMEOUT
+#define SPI_SETFOREGROUNDLOCKTIMEOUT 0x2001
+#endif
+
+#ifndef CDS_FULLSCREEN
+#define CDS_FULLSCREEN 4
+#endif
+
+#ifndef PFD_GENERIC_ACCELERATED
+#define PFD_GENERIC_ACCELERATED 0x00001000
+#endif
+#ifndef PFD_DEPTH_DONTCARE
+#define PFD_DEPTH_DONTCARE 0x20000000
+#endif
+
+#ifndef ENUM_CURRENT_SETTINGS
+#define ENUM_CURRENT_SETTINGS -1
+#endif
+#ifndef ENUM_REGISTRY_SETTINGS
+#define ENUM_REGISTRY_SETTINGS -2
+#endif
+
+#ifndef WM_MOUSEWHEEL
+#define WM_MOUSEWHEEL 0x020A
+#endif
+#ifndef WHEEL_DELTA
+#define WHEEL_DELTA 120
+#endif
+
+#ifndef WM_XBUTTONDOWN
+#define WM_XBUTTONDOWN 0x020B
+#endif
+#ifndef WM_XBUTTONUP
+#define WM_XBUTTONUP 0x020C
+#endif
+#ifndef XBUTTON1
+#define XBUTTON1 1
+#endif
+#ifndef XBUTTON2
+#define XBUTTON2 2
+#endif
+
+#ifndef WGL_ARB_pixel_format
+
+// wglSwapIntervalEXT typedef (Win32 buffer-swap interval control)
+typedef int (APIENTRY * WGLSWAPINTERVALEXT_T) (int);
+// wglGetPixelFormatAttribivARB typedef
+typedef BOOL (WINAPI * WGLGETPIXELFORMATATTRIBIVARB_T) (HDC, int, int, UINT, const int *, int *);
+// wglGetExtensionStringEXT typedef
+typedef const char *(APIENTRY * WGLGETEXTENSIONSSTRINGEXT_T)( void );
+// wglGetExtensionStringARB typedef
+typedef const char *(APIENTRY * WGLGETEXTENSIONSSTRINGARB_T)( HDC );
+
+/* Constants for wglGetPixelFormatAttribivARB */
+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
+#define WGL_DRAW_TO_WINDOW_ARB 0x2001
+#define WGL_SUPPORT_OPENGL_ARB 0x2010
+#define WGL_ACCELERATION_ARB 0x2003
+#define WGL_DOUBLE_BUFFER_ARB 0x2011
+#define WGL_STEREO_ARB 0x2012
+#define WGL_PIXEL_TYPE_ARB 0x2013
+#define WGL_COLOR_BITS_ARB 0x2014
+#define WGL_RED_BITS_ARB 0x2015
+#define WGL_GREEN_BITS_ARB 0x2017
+#define WGL_BLUE_BITS_ARB 0x2019
+#define WGL_ALPHA_BITS_ARB 0x201B
+#define WGL_ACCUM_BITS_ARB 0x201D
+#define WGL_ACCUM_RED_BITS_ARB 0x201E
+#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_STENCIL_BITS_ARB 0x2023
+#define WGL_AUX_BUFFERS_ARB 0x2024
+#define WGL_SAMPLE_BUFFERS_ARB 0x2041
+#define WGL_SAMPLES_ARB 0x2042
+
+/* Constants for WGL_ACCELERATION_ARB */
+#define WGL_NO_ACCELERATION_ARB 0x2025
+#define WGL_GENERIC_ACCELERATION_ARB 0x2026
+#define WGL_FULL_ACCELERATION_ARB 0x2027
+
+/* Constants for WGL_PIXEL_TYPE_ARB */
+#define WGL_TYPE_RGBA_ARB 0x202B
+#define WGL_TYPE_COLORINDEX_ARB 0x202C
+
+#endif /*WGL_ARB_pixel_format*/
+
+
+#ifndef WGL_ARB_create_context
+
+/* wglCreateContextAttribsARB */
+typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC, HGLRC, const int *);
+
+/* Tokens for wglCreateContextAttribsARB attributes */
+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+
+/* Bits for WGL_CONTEXT_FLAGS_ARB */
+#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+
+/* Bits for WGL_CONTEXT_PROFILE_MASK_ARB */
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+
+#endif /*WGL_ARB_create_context*/
+
+
+#ifndef GL_VERSION_3_0
+
+typedef const GLubyte * (APIENTRY *PFNGLGETSTRINGIPROC) (GLenum, GLuint);
+
+#endif /*GL_VERSION_3_0*/
+
+
+//========================================================================
+// DLLs that are loaded at glfwInit()
+//========================================================================
+
+// gdi32.dll function pointer typedefs
+#ifndef _GLFW_NO_DLOAD_GDI32
+typedef int (WINAPI * CHOOSEPIXELFORMAT_T) (HDC,CONST PIXELFORMATDESCRIPTOR*);
+typedef int (WINAPI * DESCRIBEPIXELFORMAT_T) (HDC,int,UINT,LPPIXELFORMATDESCRIPTOR);
+typedef int (WINAPI * GETPIXELFORMAT_T) (HDC);
+typedef BOOL (WINAPI * SETPIXELFORMAT_T) (HDC,int,const PIXELFORMATDESCRIPTOR*);
+typedef BOOL (WINAPI * SWAPBUFFERS_T) (HDC);
+#endif // _GLFW_NO_DLOAD_GDI32
+
+// winmm.dll function pointer typedefs
+#ifndef _GLFW_NO_DLOAD_WINMM
+typedef MMRESULT (WINAPI * JOYGETDEVCAPSA_T) (UINT,LPJOYCAPSA,UINT);
+typedef MMRESULT (WINAPI * JOYGETPOS_T) (UINT,LPJOYINFO);
+typedef MMRESULT (WINAPI * JOYGETPOSEX_T) (UINT,LPJOYINFOEX);
+typedef DWORD (WINAPI * TIMEGETTIME_T) (void);
+#endif // _GLFW_NO_DLOAD_WINMM
+
+
+// gdi32.dll shortcuts
+#ifndef _GLFW_NO_DLOAD_GDI32
+#define _glfw_ChoosePixelFormat _glfwLibrary.Libs.ChoosePixelFormat
+#define _glfw_DescribePixelFormat _glfwLibrary.Libs.DescribePixelFormat
+#define _glfw_GetPixelFormat _glfwLibrary.Libs.GetPixelFormat
+#define _glfw_SetPixelFormat _glfwLibrary.Libs.SetPixelFormat
+#define _glfw_SwapBuffers _glfwLibrary.Libs.SwapBuffers
+#else
+#define _glfw_ChoosePixelFormat ChoosePixelFormat
+#define _glfw_DescribePixelFormat DescribePixelFormat
+#define _glfw_GetPixelFormat GetPixelFormat
+#define _glfw_SetPixelFormat SetPixelFormat
+#define _glfw_SwapBuffers SwapBuffers
+#endif // _GLFW_NO_DLOAD_GDI32
+
+// winmm.dll shortcuts
+#ifndef _GLFW_NO_DLOAD_WINMM
+#define _glfw_joyGetDevCaps _glfwLibrary.Libs.joyGetDevCapsA
+#define _glfw_joyGetPos _glfwLibrary.Libs.joyGetPos
+#define _glfw_joyGetPosEx _glfwLibrary.Libs.joyGetPosEx
+#define _glfw_timeGetTime _glfwLibrary.Libs.timeGetTime
+#else
+#define _glfw_joyGetDevCaps joyGetDevCapsA
+#define _glfw_joyGetPos joyGetPos
+#define _glfw_joyGetPosEx joyGetPosEx
+#define _glfw_timeGetTime timeGetTime
+#endif // _GLFW_NO_DLOAD_WINMM
+
+
+//========================================================================
+// GLFW platform specific types
+//========================================================================
+
+//------------------------------------------------------------------------
+// Pointer length integer
+//------------------------------------------------------------------------
+typedef INT_PTR GLFWintptr;
+
+
+//------------------------------------------------------------------------
+// Window structure
+//------------------------------------------------------------------------
+typedef struct _GLFWwin_struct _GLFWwin;
+
+struct _GLFWwin_struct {
+
+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
+
+ // User callback functions
+ GLFWwindowsizefun windowSizeCallback;
+ GLFWwindowclosefun windowCloseCallback;
+ GLFWwindowrefreshfun windowRefreshCallback;
+ GLFWmousebuttonfun mouseButtonCallback;
+ GLFWmouseposfun mousePosCallback;
+ GLFWmousewheelfun mouseWheelCallback;
+ GLFWkeyfun keyCallback;
+ GLFWcharfun charCallback;
+
+ // User selected window settings
+ int fullscreen; // Fullscreen flag
+ int mouseLock; // Mouse-lock flag
+ int autoPollEvents; // Auto polling flag
+ int sysKeysDisabled; // System keys disabled flag
+ int windowNoResize; // Resize- and maximize gadgets disabled flag
+ int refreshRate; // Vertical monitor refresh rate
+
+ // Window status & parameters
+ int opened; // Flag telling if window is opened or not
+ int active; // Application active flag
+ int iconified; // Window iconified flag
+ int width, height; // Window width and heigth
+ int accelerated; // GL_TRUE if window is HW accelerated
+
+ // Framebuffer attributes
+ int redBits;
+ int greenBits;
+ int blueBits;
+ int alphaBits;
+ int depthBits;
+ int stencilBits;
+ int accumRedBits;
+ int accumGreenBits;
+ int accumBlueBits;
+ int accumAlphaBits;
+ int auxBuffers;
+ int stereo;
+ int samples;
+
+ // OpenGL extensions and context attributes
+ int has_GL_SGIS_generate_mipmap;
+ int has_GL_ARB_texture_non_power_of_two;
+ int glMajor, glMinor, glRevision;
+ int glForward, glDebug, glProfile;
+
+ PFNGLGETSTRINGIPROC GetStringi;
+
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+ // Platform specific window resources
+ HDC DC; // Private GDI device context
+ HGLRC context; // Permanent rendering context
+ HWND window; // Window handle
+ ATOM classAtom; // Window class atom
+ int modeID; // Mode ID for fullscreen mode
+ HHOOK keyboardHook; // Keyboard hook handle
+ DWORD dwStyle; // Window styles used for window creation
+ DWORD dwExStyle; // --"--
+
+ // Platform specific extensions (context specific)
+ WGLSWAPINTERVALEXT_T SwapIntervalEXT;
+ WGLGETPIXELFORMATATTRIBIVARB_T GetPixelFormatAttribivARB;
+ WGLGETEXTENSIONSSTRINGEXT_T GetExtensionsStringEXT;
+ WGLGETEXTENSIONSSTRINGARB_T GetExtensionsStringARB;
+ PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
+ GLboolean has_WGL_EXT_swap_control;
+ GLboolean has_WGL_ARB_multisample;
+ GLboolean has_WGL_ARB_pixel_format;
+ GLboolean has_WGL_ARB_create_context;
+
+ // Various platform specific internal variables
+ int oldMouseLock; // Old mouse-lock flag (used for remembering
+ // mouse-lock state when iconifying)
+ int oldMouseLockValid;
+ int desiredRefreshRate; // Desired vertical monitor refresh rate
+
+};
+
+GLFWGLOBAL _GLFWwin _glfwWin;
+
+
+//------------------------------------------------------------------------
+// User input status (most of this should go in _GLFWwin)
+//------------------------------------------------------------------------
+GLFWGLOBAL struct {
+
+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
+
+ // Mouse status
+ int MousePosX, MousePosY;
+ int WheelPos;
+ char MouseButton[ GLFW_MOUSE_BUTTON_LAST+1 ];
+
+ // Keyboard status
+ char Key[ GLFW_KEY_LAST+1 ];
+ int LastChar;
+
+ // User selected settings
+ int StickyKeys;
+ int StickyMouseButtons;
+ int KeyRepeat;
+
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+ // Platform specific internal variables
+ int MouseMoved, OldMouseX, OldMouseY;
+
+} _glfwInput;
+
+
+//------------------------------------------------------------------------
+// Library global data
+//------------------------------------------------------------------------
+GLFWGLOBAL struct {
+
+ // Window opening hints
+ _GLFWhints hints;
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+ HINSTANCE instance; // Instance of the application
+
+ // Timer data
+ struct {
+ int HasPerformanceCounter;
+ double Resolution;
+ unsigned int t0_32;
+ __int64 t0_64;
+ } Timer;
+
+ // System information
+ struct {
+ int winVer;
+ int hasUnicode;
+ DWORD foregroundLockTimeout;
+ } Sys;
+
+#if !defined(_GLFW_NO_DLOAD_WINMM) || !defined(_GLFW_NO_DLOAD_GDI32)
+ // Library handles and function pointers
+ struct {
+#ifndef _GLFW_NO_DLOAD_GDI32
+ // gdi32.dll
+ HINSTANCE gdi32;
+ CHOOSEPIXELFORMAT_T ChoosePixelFormat;
+ DESCRIBEPIXELFORMAT_T DescribePixelFormat;
+ GETPIXELFORMAT_T GetPixelFormat;
+ SETPIXELFORMAT_T SetPixelFormat;
+ SWAPBUFFERS_T SwapBuffers;
+#endif // _GLFW_NO_DLOAD_GDI32
+
+ // winmm.dll
+#ifndef _GLFW_NO_DLOAD_WINMM
+ HINSTANCE winmm;
+ JOYGETDEVCAPSA_T joyGetDevCapsA;
+ JOYGETPOS_T joyGetPos;
+ JOYGETPOSEX_T joyGetPosEx;
+ TIMEGETTIME_T timeGetTime;
+#endif // _GLFW_NO_DLOAD_WINMM
+ } Libs;
+#endif
+
+} _glfwLibrary;
+
+
+//========================================================================
+// Various Windows version constants
+//========================================================================
+
+#define _GLFW_WIN_UNKNOWN 0x0000 // Earlier than 95 or NT4
+#define _GLFW_WIN_95 0x0001
+#define _GLFW_WIN_98 0x0002
+#define _GLFW_WIN_ME 0x0003
+#define _GLFW_WIN_UNKNOWN_9x 0x0004 // Later than ME
+#define _GLFW_WIN_NT4 0x0101
+#define _GLFW_WIN_2K 0x0102
+#define _GLFW_WIN_XP 0x0103
+#define _GLFW_WIN_NET_SERVER 0x0104
+#define _GLFW_WIN_UNKNOWN_NT 0x0105 // Later than .NET Server
+
+
+//========================================================================
+// Prototypes for platform specific internal functions
+//========================================================================
+
+// Time
+void _glfwInitTimer( void );
+
+// Fullscreen support
+int _glfwGetClosestVideoModeBPP( int *w, int *h, int *bpp, int *refresh );
+int _glfwGetClosestVideoMode( int *w, int *h, int *r, int *g, int *b, int *refresh );
+void _glfwSetVideoModeMODE( int mode );
+void _glfwSetVideoMode( int *w, int *h, int r, int g, int b, int refresh );
+
+
+#endif // _platform_h_
diff --git a/lib/win32/win32_dllmain.c b/lib/win32/win32_dllmain.c
new file mode 100644
index 00000000..d7a9c1a9
--- /dev/null
+++ b/lib/win32/win32_dllmain.c
@@ -0,0 +1,49 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Win32/WGL
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+#if defined(GLFW_BUILD_DLL)
+
+//========================================================================
+// GLFW DLL entry point
+//========================================================================
+
+BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, LPVOID reserved )
+{
+ // NOTE: Some compilers complains about instance and x never being used -
+ // never mind that (we don't want to use them)!
+
+ return TRUE;
+}
+
+#endif // GLFW_BUILD_DLL
+
diff --git a/lib/win32/win32_enable.c b/lib/win32/win32_enable.c
new file mode 100644
index 00000000..3e72b787
--- /dev/null
+++ b/lib/win32/win32_enable.c
@@ -0,0 +1,155 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Win32/WGL
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+//========================================================================
+// Low level keyboard hook (system callback) function
+// Used to disable system keys under Windows NT
+//========================================================================
+
+static LRESULT CALLBACK keyboardHook( int nCode, WPARAM wParam, LPARAM lParam )
+{
+ BOOL syskeys = FALSE;
+ PKBDLLHOOKSTRUCT p;
+
+ // We are only looking for keyboard events - interpret lParam as a
+ // pointer to a KBDLLHOOKSTRUCT
+ p = (PKBDLLHOOKSTRUCT) lParam;
+
+ if( nCode == HC_ACTION )
+ {
+ // We have a keyboard event
+
+ switch( wParam )
+ {
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ // Detect: ALT+TAB, ALT+ESC, ALT+F4, CTRL+ESC,
+ // LWIN, RWIN, APPS (mysterious menu key)
+ syskeys = ( p->vkCode == VK_TAB &&
+ p->flags & LLKHF_ALTDOWN ) ||
+ ( p->vkCode == VK_ESCAPE &&
+ p->flags & LLKHF_ALTDOWN ) ||
+ ( p->vkCode == VK_F4 &&
+ p->flags & LLKHF_ALTDOWN ) ||
+ ( p->vkCode == VK_ESCAPE &&
+ (GetKeyState(VK_CONTROL) & 0x8000)) ||
+ p->vkCode == VK_LWIN ||
+ p->vkCode == VK_RWIN ||
+ p->vkCode == VK_APPS;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ // Was it a system key combination (e.g. ALT+TAB)?
+ if( syskeys )
+ {
+ // Pass the key event to our window message loop
+ if( _glfwWin.opened )
+ {
+ PostMessage( _glfwWin.window, (UINT) wParam, p->vkCode, 0 );
+ }
+
+ // We've taken care of it - don't let the system know about this
+ // key event
+ return 1;
+ }
+ else
+ {
+ // It's a harmless key press, let the system deal with it
+ return CallNextHookEx( _glfwWin.keyboardHook, nCode, wParam, lParam );
+ }
+}
+
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Enable system keys
+//========================================================================
+
+void _glfwPlatformEnableSystemKeys( void )
+{
+ BOOL dummy;
+
+ // Use different methods depending on operating system version
+ if( _glfwLibrary.Sys.winVer >= _GLFW_WIN_NT4 )
+ {
+ if( _glfwWin.keyboardHook != NULL )
+ {
+ UnhookWindowsHookEx( _glfwWin.keyboardHook );
+ _glfwWin.keyboardHook = NULL;
+ }
+ }
+ else
+ {
+ (void) SystemParametersInfo( SPI_SETSCREENSAVERRUNNING, FALSE, &dummy, 0 );
+ }
+}
+
+//========================================================================
+// Disable system keys
+//========================================================================
+
+void _glfwPlatformDisableSystemKeys( void )
+{
+ BOOL dummy;
+
+ // Use different methods depending on operating system version
+ if( _glfwLibrary.Sys.winVer >= _GLFW_WIN_NT4 )
+ {
+ // Under Windows NT, install a low level keyboard hook
+ _glfwWin.keyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL,
+ keyboardHook,
+ _glfwLibrary.instance,
+ 0 );
+ }
+ else
+ {
+ // Under Windows 95/98/ME, fool Windows that a screensaver
+ // is running => prevents ALT+TAB, CTRL+ESC and CTRL+ALT+DEL
+ (void) SystemParametersInfo( SPI_SETSCREENSAVERRUNNING, TRUE, &dummy, 0 );
+ }
+}
+
diff --git a/lib/win32/win32_fullscreen.c b/lib/win32/win32_fullscreen.c
new file mode 100644
index 00000000..5784d797
--- /dev/null
+++ b/lib/win32/win32_fullscreen.c
@@ -0,0 +1,320 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Win32/WGL
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+//========================================================================
+// Convert BPP to RGB bits based on "best guess"
+//========================================================================
+
+static void bpp2rgb( int bpp, int *r, int *g, int *b )
+{
+ int delta;
+
+ // We assume that by 32 they really meant 24
+ if( bpp == 32 )
+ {
+ bpp = 24;
+ }
+
+ // Convert "bits per pixel" to red, green & blue sizes
+
+ *r = *g = *b = bpp / 3;
+ delta = bpp - (*r * 3);
+ if( delta >= 1 )
+ {
+ *g = *g + 1;
+ }
+ if( delta == 2 )
+ {
+ *r = *r + 1;
+ }
+}
+
+
+//========================================================================
+// Return closest video mode by dimensions, refresh rate and bits per pixel
+//========================================================================
+
+int _glfwGetClosestVideoModeBPP( int *w, int *h, int *bpp, int *refresh )
+{
+ int mode, bestmode, match, bestmatch, rr, bestrr, success;
+ DEVMODE dm;
+
+ // Find best match
+ bestmatch = 0x7fffffff;
+ bestrr = 0x7fffffff;
+ mode = bestmode = 0;
+ do
+ {
+ dm.dmSize = sizeof( DEVMODE );
+ success = EnumDisplaySettings( NULL, mode, &dm );
+ if( success )
+ {
+ match = dm.dmBitsPerPel - *bpp;
+ if( match < 0 ) match = -match;
+ match = ( match << 25 ) |
+ ( (dm.dmPelsWidth - *w) *
+ (dm.dmPelsWidth - *w) +
+ (dm.dmPelsHeight - *h) *
+ (dm.dmPelsHeight - *h) );
+ if( match < bestmatch )
+ {
+ bestmatch = match;
+ bestmode = mode;
+ bestrr = (dm.dmDisplayFrequency - *refresh) *
+ (dm.dmDisplayFrequency - *refresh);
+ }
+ else if( match == bestmatch && *refresh > 0 )
+ {
+ rr = (dm.dmDisplayFrequency - *refresh) *
+ (dm.dmDisplayFrequency - *refresh);
+ if( rr < bestrr )
+ {
+ bestmatch = match;
+ bestmode = mode;
+ bestrr = rr;
+ }
+ }
+ }
+ mode ++;
+ }
+ while( success );
+
+ // Get the parameters for the best matching display mode
+ dm.dmSize = sizeof( DEVMODE );
+ (void) EnumDisplaySettings( NULL, bestmode, &dm );
+
+ // Fill out actual width and height
+ *w = dm.dmPelsWidth;
+ *h = dm.dmPelsHeight;
+
+ // Return bits per pixel
+ *bpp = dm.dmBitsPerPel;
+
+ // Return vertical refresh rate
+ *refresh = dm.dmDisplayFrequency;
+
+ return bestmode;
+}
+
+
+//========================================================================
+// Return closest video mode by dimensions, refresh rate and channel sizes
+//========================================================================
+
+static int getClosestVideoMode( int *w, int *h,
+ int *r, int *g, int *b,
+ int *refresh )
+{
+ int bpp, bestmode;
+
+ // Colorbits = sum of red/green/blue bits
+ bpp = *r + *g + *b;
+
+ // If colorbits < 15 (e.g. 0) or >= 24, default to 32 bpp
+ if( bpp < 15 || bpp >= 24 )
+ {
+ bpp = 32;
+ }
+
+ // Find best match
+ bestmode = _glfwGetClosestVideoModeBPP( w, h, &bpp, refresh );
+
+ // Convert "bits per pixel" to red, green & blue sizes
+ bpp2rgb( bpp, r, g, b );
+
+ return bestmode;
+}
+
+
+//========================================================================
+// Change the current video mode
+//========================================================================
+
+void _glfwSetVideoModeMODE( int mode )
+{
+ DEVMODE dm;
+ int success;
+
+ // Get the parameters for the best matching display mode
+ dm.dmSize = sizeof( DEVMODE );
+ (void) EnumDisplaySettings( NULL, mode, &dm );
+
+ // Set which fields we want to specify
+ dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
+
+ // Do we have a prefered refresh rate?
+ if( _glfwWin.desiredRefreshRate > 0 )
+ {
+ dm.dmFields = dm.dmFields | DM_DISPLAYFREQUENCY;
+ dm.dmDisplayFrequency = _glfwWin.desiredRefreshRate;
+ }
+
+ // Change display setting
+ dm.dmSize = sizeof( DEVMODE );
+ success = ChangeDisplaySettings( &dm, CDS_FULLSCREEN );
+
+ // If the mode change was not possible, query the current display
+ // settings (we'll use the desktop resolution for fullscreen mode)
+ if( success == DISP_CHANGE_SUCCESSFUL )
+ {
+ _glfwWin.modeID = mode;
+ }
+ else
+ {
+ _glfwWin.modeID = ENUM_REGISTRY_SETTINGS;
+ EnumDisplaySettings( NULL, ENUM_REGISTRY_SETTINGS, &dm );
+ }
+
+ // Set the window size to that of the display mode
+ _glfwWin.width = dm.dmPelsWidth;
+ _glfwWin.height = dm.dmPelsHeight;
+}
+
+
+//========================================================================
+// _glfwSetVideoMode() - Change the current video mode
+//========================================================================
+
+void _glfwSetVideoMode( int *w, int *h, int r, int g, int b, int refresh )
+{
+ int bestmode;
+
+ // Find a best match mode
+ bestmode = getClosestVideoMode( w, h, &r, &g, &b, &refresh );
+
+ // Change mode
+ _glfwSetVideoModeMODE( bestmode );
+}
+
+
+//************************************************************************
+//**** GLFW user functions ****
+//************************************************************************
+
+//========================================================================
+// _glfwPlatformGetVideoModes() - Get a list of available video modes
+//========================================================================
+
+int _glfwPlatformGetVideoModes( GLFWvidmode *list, int maxcount )
+{
+ int count, success, mode, i, j;
+ int m1, m2, bpp, r, g, b;
+ DEVMODE dm;
+
+ // Loop through all video modes and extract all the UNIQUE modes
+ count = 0;
+ mode = 0;
+ do
+ {
+ // Get video mode properties
+ dm.dmSize = sizeof( DEVMODE );
+ success = EnumDisplaySettings( NULL, mode, &dm );
+
+ // Is it a valid mode? (only list depths >= 15 bpp)
+ if( success && dm.dmBitsPerPel >= 15 )
+ {
+ // Convert to RGB, and back to bpp ("mask out" alpha bits etc)
+ bpp2rgb( dm.dmBitsPerPel, &r, &g, &b );
+ bpp = r + g + b;
+
+ // Mode "code" for this mode
+ m1 = (bpp << 25) | (dm.dmPelsWidth * dm.dmPelsHeight);
+
+ // Insert mode in list (sorted), and avoid duplicates
+ for( i = 0; i < count; i ++ )
+ {
+ // Mode "code" for already listed mode
+ bpp = list[i].RedBits + list[i].GreenBits +
+ list[i].BlueBits;
+ m2 = (bpp << 25) | (list[i].Width * list[i].Height);
+ if( m1 <= m2 )
+ {
+ break;
+ }
+ }
+
+ // New entry at the end of the list?
+ if( i >= count )
+ {
+ list[count].Width = dm.dmPelsWidth;
+ list[count].Height = dm.dmPelsHeight;
+ list[count].RedBits = r;
+ list[count].GreenBits = g;
+ list[count].BlueBits = b;
+ count ++;
+ }
+ // Insert new entry in the list?
+ else if( m1 < m2 )
+ {
+ for( j = count; j > i; j -- )
+ {
+ list[j] = list[j-1];
+ }
+ list[i].Width = dm.dmPelsWidth;
+ list[i].Height = dm.dmPelsHeight;
+ list[i].RedBits = r;
+ list[i].GreenBits = g;
+ list[i].BlueBits = b;
+ count ++;
+ }
+ }
+ mode ++;
+ }
+ while( success && (count < maxcount) );
+
+ return count;
+}
+
+
+//========================================================================
+// Get the desktop video mode
+//========================================================================
+
+void _glfwPlatformGetDesktopMode( GLFWvidmode *mode )
+{
+ DEVMODE dm;
+
+ // Get desktop display mode
+ dm.dmSize = sizeof( DEVMODE );
+ (void) EnumDisplaySettings( NULL, ENUM_REGISTRY_SETTINGS, &dm );
+
+ // Return desktop mode parameters
+ mode->Width = dm.dmPelsWidth;
+ mode->Height = dm.dmPelsHeight;
+ bpp2rgb( dm.dmBitsPerPel, &mode->RedBits, &mode->GreenBits, &mode->BlueBits );
+}
+
diff --git a/lib/win32/win32_glext.c b/lib/win32/win32_glext.c
new file mode 100644
index 00000000..820adc50
--- /dev/null
+++ b/lib/win32/win32_glext.c
@@ -0,0 +1,82 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Win32/WGL
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Check if the current context supports the specified WGL extension
+//========================================================================
+
+int _glfwPlatformExtensionSupported( const char *extension )
+{
+ const GLubyte *extensions;
+
+ if( _glfwWin.GetExtensionsStringEXT != NULL )
+ {
+ extensions = (GLubyte *) _glfwWin.GetExtensionsStringEXT();
+ if( extensions != NULL )
+ {
+ if( _glfwStringInExtensionString( extension, extensions ) )
+ {
+ return GL_TRUE;
+ }
+ }
+ }
+
+ if( _glfwWin.GetExtensionsStringARB != NULL )
+ {
+ extensions = (GLubyte *) _glfwWin.GetExtensionsStringARB( _glfwWin.DC );
+ if( extensions != NULL )
+ {
+ if( _glfwStringInExtensionString( extension, extensions ) )
+ {
+ return GL_TRUE;
+ }
+ }
+ }
+
+ return GL_FALSE;
+}
+
+
+//========================================================================
+// Get the function pointer to an OpenGL function
+//========================================================================
+
+void *_glfwPlatformGetProcAddress( const char *procname )
+{
+ return (void *) wglGetProcAddress( procname );
+}
+
diff --git a/lib/win32/win32_init.c b/lib/win32/win32_init.c
new file mode 100644
index 00000000..8ad41af1
--- /dev/null
+++ b/lib/win32/win32_init.c
@@ -0,0 +1,281 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Win32/WGL
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+// With the Borland C++ compiler, we want to disable FPU exceptions
+#ifdef __BORLANDC__
+#include
+#endif // __BORLANDC__
+
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+//========================================================================
+// _glfwInitLibraries() - Load necessary libraries (DLLs)
+//========================================================================
+
+static int _glfwInitLibraries( void )
+{
+ // gdi32.dll (OpenGL pixel format functions & SwapBuffers)
+#ifndef _GLFW_NO_DLOAD_GDI32
+ _glfwLibrary.Libs.gdi32 = LoadLibrary( "gdi32.dll" );
+ if( _glfwLibrary.Libs.gdi32 != NULL )
+ {
+ _glfwLibrary.Libs.ChoosePixelFormat = (CHOOSEPIXELFORMAT_T)
+ GetProcAddress( _glfwLibrary.Libs.gdi32, "ChoosePixelFormat" );
+ _glfwLibrary.Libs.DescribePixelFormat = (DESCRIBEPIXELFORMAT_T)
+ GetProcAddress( _glfwLibrary.Libs.gdi32, "DescribePixelFormat" );
+ _glfwLibrary.Libs.GetPixelFormat = (GETPIXELFORMAT_T)
+ GetProcAddress( _glfwLibrary.Libs.gdi32, "GetPixelFormat" );
+ _glfwLibrary.Libs.SetPixelFormat = (SETPIXELFORMAT_T)
+ GetProcAddress( _glfwLibrary.Libs.gdi32, "SetPixelFormat" );
+ _glfwLibrary.Libs.SwapBuffers = (SWAPBUFFERS_T)
+ GetProcAddress( _glfwLibrary.Libs.gdi32, "SwapBuffers" );
+ if( _glfwLibrary.Libs.ChoosePixelFormat == NULL ||
+ _glfwLibrary.Libs.DescribePixelFormat == NULL ||
+ _glfwLibrary.Libs.GetPixelFormat == NULL ||
+ _glfwLibrary.Libs.SetPixelFormat == NULL ||
+ _glfwLibrary.Libs.SwapBuffers == NULL )
+ {
+ FreeLibrary( _glfwLibrary.Libs.gdi32 );
+ _glfwLibrary.Libs.gdi32 = NULL;
+ return GL_FALSE;
+ }
+ }
+ else
+ {
+ return GL_FALSE;
+ }
+#endif // _GLFW_NO_DLOAD_GDI32
+
+ // winmm.dll (for joystick and timer support)
+#ifndef _GLFW_NO_DLOAD_WINMM
+ _glfwLibrary.Libs.winmm = LoadLibrary( "winmm.dll" );
+ if( _glfwLibrary.Libs.winmm != NULL )
+ {
+ _glfwLibrary.Libs.joyGetDevCapsA = (JOYGETDEVCAPSA_T)
+ GetProcAddress( _glfwLibrary.Libs.winmm, "joyGetDevCapsA" );
+ _glfwLibrary.Libs.joyGetPos = (JOYGETPOS_T)
+ GetProcAddress( _glfwLibrary.Libs.winmm, "joyGetPos" );
+ _glfwLibrary.Libs.joyGetPosEx = (JOYGETPOSEX_T)
+ GetProcAddress( _glfwLibrary.Libs.winmm, "joyGetPosEx" );
+ _glfwLibrary.Libs.timeGetTime = (TIMEGETTIME_T)
+ GetProcAddress( _glfwLibrary.Libs.winmm, "timeGetTime" );
+ if( _glfwLibrary.Libs.joyGetDevCapsA == NULL ||
+ _glfwLibrary.Libs.joyGetPos == NULL ||
+ _glfwLibrary.Libs.joyGetPosEx == NULL ||
+ _glfwLibrary.Libs.timeGetTime == NULL )
+ {
+ FreeLibrary( _glfwLibrary.Libs.winmm );
+ _glfwLibrary.Libs.winmm = NULL;
+ return GL_FALSE;
+ }
+ }
+ else
+ {
+ return GL_FALSE;
+ }
+#endif // _GLFW_NO_DLOAD_WINMM
+
+ return GL_TRUE;
+}
+
+
+//========================================================================
+// _glfwFreeLibraries() - Unload used libraries (DLLs)
+//========================================================================
+
+static void _glfwFreeLibraries( void )
+{
+ // gdi32.dll
+#ifndef _GLFW_NO_DLOAD_GDI32
+ if( _glfwLibrary.Libs.gdi32 != NULL )
+ {
+ FreeLibrary( _glfwLibrary.Libs.gdi32 );
+ _glfwLibrary.Libs.gdi32 = NULL;
+ }
+#endif // _GLFW_NO_DLOAD_GDI32
+
+ // winmm.dll
+#ifndef _GLFW_NO_DLOAD_WINMM
+ if( _glfwLibrary.Libs.winmm != NULL )
+ {
+ FreeLibrary( _glfwLibrary.Libs.winmm );
+ _glfwLibrary.Libs.winmm = NULL;
+ }
+#endif // _GLFW_NO_DLOAD_WINMM
+}
+
+
+//========================================================================
+// _glfwTerminate_atexit() - Terminate GLFW when exiting application
+//========================================================================
+
+void _glfwTerminate_atexit( void )
+{
+ glfwTerminate();
+}
+
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// _glfwPlatformInit() - Initialize various GLFW state
+//========================================================================
+
+int _glfwPlatformInit( void )
+{
+ OSVERSIONINFO osi;
+
+ // 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)
+ SystemParametersInfo( SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
+ &_glfwLibrary.Sys.foregroundLockTimeout, 0 );
+ SystemParametersInfo( SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0,
+ SPIF_SENDCHANGE );
+
+ // Check which OS version we are running
+ osi.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
+ GetVersionEx( &osi );
+ _glfwLibrary.Sys.winVer = _GLFW_WIN_UNKNOWN;
+ if( osi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
+ {
+ if( osi.dwMajorVersion == 4 && osi.dwMinorVersion < 10 )
+ {
+ _glfwLibrary.Sys.winVer = _GLFW_WIN_95;
+ }
+ else if( osi.dwMajorVersion == 4 && osi.dwMinorVersion < 90 )
+ {
+ _glfwLibrary.Sys.winVer = _GLFW_WIN_98;
+ }
+ else if( osi.dwMajorVersion == 4 && osi.dwMinorVersion == 90 )
+ {
+ _glfwLibrary.Sys.winVer = _GLFW_WIN_ME;
+ }
+ else if( osi.dwMajorVersion >= 4 )
+ {
+ _glfwLibrary.Sys.winVer = _GLFW_WIN_UNKNOWN_9x;
+ }
+ }
+ else if( osi.dwPlatformId == VER_PLATFORM_WIN32_NT )
+ {
+ if( osi.dwMajorVersion == 4 && osi.dwMinorVersion == 0 )
+ {
+ _glfwLibrary.Sys.winVer = _GLFW_WIN_NT4;
+ }
+ else if( osi.dwMajorVersion == 5 && osi.dwMinorVersion == 0 )
+ {
+ _glfwLibrary.Sys.winVer = _GLFW_WIN_2K;
+ }
+ else if( osi.dwMajorVersion == 5 && osi.dwMinorVersion == 1 )
+ {
+ _glfwLibrary.Sys.winVer = _GLFW_WIN_XP;
+ }
+ else if( osi.dwMajorVersion == 5 && osi.dwMinorVersion == 2 )
+ {
+ _glfwLibrary.Sys.winVer = _GLFW_WIN_NET_SERVER;
+ }
+ else if( osi.dwMajorVersion >= 5 )
+ {
+ _glfwLibrary.Sys.winVer = _GLFW_WIN_UNKNOWN_NT;
+ }
+ }
+
+ // Do we have Unicode support?
+ if( _glfwLibrary.Sys.winVer >= _GLFW_WIN_NT4 )
+ {
+ // Windows NT/2000/XP/.NET has Unicode support
+ _glfwLibrary.Sys.hasUnicode = GL_TRUE;
+ }
+ else
+ {
+ // Windows 9x/ME does not have Unicode support
+ _glfwLibrary.Sys.hasUnicode = GL_FALSE;
+ }
+
+ // Load libraries (DLLs)
+ if( !_glfwInitLibraries() )
+ {
+ return GL_FALSE;
+ }
+
+ // With the Borland C++ compiler, we want to disable FPU exceptions
+ // (this is recommended for OpenGL applications under Windows)
+#ifdef __BORLANDC__
+ _control87( MCW_EM, MCW_EM );
+#endif
+
+ // Retrieve GLFW instance handle
+ _glfwLibrary.instance = GetModuleHandle( NULL );
+
+ // System keys are not disabled
+ _glfwWin.keyboardHook = NULL;
+
+ // Install atexit() routine
+ atexit( _glfwTerminate_atexit );
+
+ // Start the timer
+ _glfwInitTimer();
+
+ return GL_TRUE;
+}
+
+
+//========================================================================
+// Close window and shut down library
+//========================================================================
+
+int _glfwPlatformTerminate( void )
+{
+ // Close OpenGL window
+ glfwCloseWindow();
+
+ // Enable system keys again (if they were disabled)
+ glfwEnable( GLFW_SYSTEM_KEYS );
+
+ // Unload libraries (DLLs)
+ _glfwFreeLibraries();
+
+ // Restore FOREGROUNDLOCKTIMEOUT system setting
+ SystemParametersInfo( SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
+ (LPVOID)_glfwLibrary.Sys.foregroundLockTimeout,
+ SPIF_SENDCHANGE );
+
+ return GL_TRUE;
+}
+
diff --git a/lib/win32/win32_joystick.c b/lib/win32/win32_joystick.c
new file mode 100644
index 00000000..64b55899
--- /dev/null
+++ b/lib/win32/win32_joystick.c
@@ -0,0 +1,234 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Win32/WGL
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+//========================================================================
+// _glfwJoystickPresent() - Return GL_TRUE if joystick is present,
+// else return GL_FALSE.
+//========================================================================
+
+static int _glfwJoystickPresent( int joy )
+{
+ JOYINFO ji;
+
+ // Windows NT 4.0 MMSYSTEM only supports 2 sticks (other Windows
+ // versions support 16 sticks)
+ if( _glfwLibrary.Sys.winVer == _GLFW_WIN_NT4 && joy > GLFW_JOYSTICK_2 )
+ {
+ return GL_FALSE;
+ }
+
+ // Is it a valid stick ID (Windows don't support more than 16 sticks)?
+ if( joy < GLFW_JOYSTICK_1 || joy > GLFW_JOYSTICK_16 )
+ {
+ return GL_FALSE;
+ }
+
+ // Is the joystick present?
+ if( _glfw_joyGetPos( joy - GLFW_JOYSTICK_1, &ji ) != JOYERR_NOERROR )
+ {
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+//========================================================================
+// _glfwCalcJoystickPos() - Calculate joystick position
+//========================================================================
+
+static float _glfwCalcJoystickPos( DWORD pos, DWORD min, DWORD max )
+{
+ float fpos = (float) pos;
+ float fmin = (float) min;
+ float fmax = (float) max;
+ return (2.0f*(fpos - fmin) / (fmax - fmin)) - 1.0f;
+}
+
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// _glfwPlatformGetJoystickParam() - Determine joystick capabilities
+//========================================================================
+
+int _glfwPlatformGetJoystickParam( int joy, int param )
+{
+ JOYCAPS jc;
+
+// return 0;
+
+ // Is joystick present?
+ if( !_glfwJoystickPresent( joy ) )
+ {
+ return 0;
+ }
+
+ // We got this far, the joystick is present
+ if( param == GLFW_PRESENT )
+ {
+ return GL_TRUE;
+ }
+
+ // Get joystick capabilities
+ _glfw_joyGetDevCaps( joy - GLFW_JOYSTICK_1, &jc, sizeof(JOYCAPS) );
+
+ switch( param )
+ {
+ case GLFW_AXES:
+ // Return number of joystick axes
+ return jc.wNumAxes;
+
+ case GLFW_BUTTONS:
+ // Return number of joystick axes
+ return jc.wNumButtons;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+//========================================================================
+// _glfwPlatformGetJoystickPos() - Get joystick axis positions
+//========================================================================
+
+int _glfwPlatformGetJoystickPos( int joy, float *pos, int numaxes )
+{
+ JOYCAPS jc;
+ JOYINFOEX ji;
+ int axis;
+
+// return 0;
+
+ // Is joystick present?
+ if( !_glfwJoystickPresent( joy ) )
+ {
+ return 0;
+ }
+
+ // Get joystick capabilities
+ _glfw_joyGetDevCaps( joy - GLFW_JOYSTICK_1, &jc, sizeof(JOYCAPS) );
+
+ // Get joystick state
+ ji.dwSize = sizeof( JOYINFOEX );
+ ji.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ |
+ JOY_RETURNR | JOY_RETURNU | JOY_RETURNV;
+ _glfw_joyGetPosEx( joy - GLFW_JOYSTICK_1, &ji );
+
+ // Get position values for all axes
+ axis = 0;
+ if( axis < numaxes )
+ {
+ pos[ axis++ ] = _glfwCalcJoystickPos( ji.dwXpos, jc.wXmin,
+ jc.wXmax );
+ }
+ if( axis < numaxes )
+ {
+ pos[ axis++ ] = -_glfwCalcJoystickPos( ji.dwYpos, jc.wYmin,
+ jc.wYmax );
+ }
+ if( axis < numaxes && jc.wCaps & JOYCAPS_HASZ )
+ {
+ pos[ axis++ ] = _glfwCalcJoystickPos( ji.dwZpos, jc.wZmin,
+ jc.wZmax );
+ }
+ if( axis < numaxes && jc.wCaps & JOYCAPS_HASR )
+ {
+ pos[ axis++ ] = _glfwCalcJoystickPos( ji.dwRpos, jc.wRmin,
+ jc.wRmax );
+ }
+ if( axis < numaxes && jc.wCaps & JOYCAPS_HASU )
+ {
+ pos[ axis++ ] = _glfwCalcJoystickPos( ji.dwUpos, jc.wUmin,
+ jc.wUmax );
+ }
+ if( axis < numaxes && jc.wCaps & JOYCAPS_HASV )
+ {
+ pos[ axis++ ] = -_glfwCalcJoystickPos( ji.dwVpos, jc.wVmin,
+ jc.wVmax );
+ }
+
+ // Return number of returned axes
+ return axis;
+}
+
+
+//========================================================================
+// _glfwPlatformGetJoystickButtons() - Get joystick button states
+//========================================================================
+
+int _glfwPlatformGetJoystickButtons( int joy, unsigned char *buttons,
+ int numbuttons )
+{
+ JOYCAPS jc;
+ JOYINFOEX ji;
+ int button;
+
+// return 0;
+
+ // Is joystick present?
+ if( !_glfwJoystickPresent( joy ) )
+ {
+ return 0;
+ }
+
+ // Get joystick capabilities
+ _glfw_joyGetDevCaps( joy - GLFW_JOYSTICK_1, &jc, sizeof(JOYCAPS) );
+
+ // Get joystick state
+ ji.dwSize = sizeof( JOYINFOEX );
+ ji.dwFlags = JOY_RETURNBUTTONS;
+ _glfw_joyGetPosEx( joy - GLFW_JOYSTICK_1, &ji );
+
+ // Get states of all requested buttons
+ button = 0;
+ while( button < numbuttons && button < (int) jc.wNumButtons )
+ {
+ buttons[ button ] = (unsigned char)
+ (ji.dwButtons & (1UL << button) ? GLFW_PRESS : GLFW_RELEASE);
+ button ++;
+ }
+
+ return button;
+}
+
diff --git a/lib/win32/win32_time.c b/lib/win32/win32_time.c
new file mode 100644
index 00000000..6bd112c3
--- /dev/null
+++ b/lib/win32/win32_time.c
@@ -0,0 +1,118 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Win32/WGL
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+//========================================================================
+// _glfwInitTimer() - Initialise timer
+//========================================================================
+
+void _glfwInitTimer( void )
+{
+ __int64 freq;
+
+ // Check if we have a performance counter
+ if( QueryPerformanceFrequency( (LARGE_INTEGER *)&freq ) )
+ {
+ // Performance counter is available => use it!
+ _glfwLibrary.Timer.HasPerformanceCounter = GL_TRUE;
+
+ // Counter resolution is 1 / counter frequency
+ _glfwLibrary.Timer.Resolution = 1.0 / (double)freq;
+
+ // Set start time for timer
+ QueryPerformanceCounter( (LARGE_INTEGER *)&_glfwLibrary.Timer.t0_64 );
+ }
+ else
+ {
+ // No performace counter available => use the tick counter
+ _glfwLibrary.Timer.HasPerformanceCounter = GL_FALSE;
+
+ // Counter resolution is 1 ms
+ _glfwLibrary.Timer.Resolution = 0.001;
+
+ // Set start time for timer
+ _glfwLibrary.Timer.t0_32 = _glfw_timeGetTime();
+ }
+}
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Return timer value in seconds
+//========================================================================
+
+double _glfwPlatformGetTime( void )
+{
+ double t;
+ __int64 t_64;
+
+ if( _glfwLibrary.Timer.HasPerformanceCounter )
+ {
+ QueryPerformanceCounter( (LARGE_INTEGER *)&t_64 );
+ t = (double)(t_64 - _glfwLibrary.Timer.t0_64);
+ }
+ else
+ {
+ t = (double)(_glfw_timeGetTime() - _glfwLibrary.Timer.t0_32);
+ }
+
+ // Calculate the current time in seconds
+ return t * _glfwLibrary.Timer.Resolution;
+}
+
+
+//========================================================================
+// Set timer value in seconds
+//========================================================================
+
+void _glfwPlatformSetTime( double t )
+{
+ __int64 t_64;
+
+ if( _glfwLibrary.Timer.HasPerformanceCounter )
+ {
+ QueryPerformanceCounter( (LARGE_INTEGER *)&t_64 );
+ _glfwLibrary.Timer.t0_64 = t_64 - (__int64)(t/_glfwLibrary.Timer.Resolution);
+ }
+ else
+ {
+ _glfwLibrary.Timer.t0_32 = _glfw_timeGetTime() - (int)(t*1000.0);
+ }
+}
+
diff --git a/lib/win32/win32_window.c b/lib/win32/win32_window.c
new file mode 100644
index 00000000..15071c36
--- /dev/null
+++ b/lib/win32/win32_window.c
@@ -0,0 +1,1817 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Win32/WGL
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+// We use versioned window class names in order not to cause conflicts
+// between applications using different versions of GLFW
+#define _GLFW_WNDCLASSNAME "GLFW27"
+
+
+//========================================================================
+// Enable/disable minimize/restore animations
+//========================================================================
+
+static int setMinMaxAnimations( int enable )
+{
+ ANIMATIONINFO AI;
+ int old_enable;
+
+ // Get old animation setting
+ AI.cbSize = sizeof( ANIMATIONINFO );
+ SystemParametersInfo( SPI_GETANIMATION, AI.cbSize, &AI, 0 );
+ old_enable = AI.iMinAnimate;
+
+ // If requested, change setting
+ if( old_enable != enable )
+ {
+ AI.iMinAnimate = enable;
+ SystemParametersInfo( SPI_SETANIMATION, AI.cbSize, &AI,
+ SPIF_SENDCHANGE );
+ }
+
+ return old_enable;
+}
+
+
+//========================================================================
+// Focus the window and bring it to the top of the stack
+// Due to some nastiness with how Win98/ME/2k/XP handles SetForegroundWindow,
+// we have to go through some really bizarre measures to achieve this
+//========================================================================
+
+static void setForegroundWindow( HWND hWnd )
+{
+ int try_count = 0;
+ int old_animate;
+
+ // Try the standard approach first...
+ BringWindowToTop( hWnd );
+ SetForegroundWindow( hWnd );
+
+ // If it worked, return now
+ if( hWnd == GetForegroundWindow() )
+ {
+ // Try to modify the system settings (since this is the foreground
+ // process, we are allowed to do this)
+ SystemParametersInfo( SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0,
+ SPIF_SENDCHANGE );
+ return;
+ }
+
+ // For other Windows versions than 95 & NT4.0, the standard approach
+ // may not work, so if we failed we have to "trick" Windows into
+ // making our window the foureground window: Iconify and restore
+ // again. It is ugly, but it seems to work (we turn off those annoying
+ // zoom animations to make it look a bit better at least).
+
+ // Turn off minimize/restore animations
+ old_animate = setMinMaxAnimations( 0 );
+
+ // We try this a few times, just to be on the safe side of things...
+ do
+ {
+ // Iconify & restore
+ ShowWindow( hWnd, SW_HIDE );
+ ShowWindow( hWnd, SW_SHOWMINIMIZED );
+ ShowWindow( hWnd, SW_SHOWNORMAL );
+
+ // Try to get focus
+ BringWindowToTop( hWnd );
+ SetForegroundWindow( hWnd );
+
+ // We do not want to keep going on forever, so we keep track of
+ // how many times we tried
+ try_count ++;
+ }
+ while( hWnd != GetForegroundWindow() && try_count <= 3 );
+
+ // Restore the system minimize/restore animation setting
+ (void) setMinMaxAnimations( old_animate );
+
+ // Try to modify the system settings (since this is now hopefully the
+ // foreground process, we are probably allowed to do this)
+ SystemParametersInfo( SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0,
+ SPIF_SENDCHANGE );
+}
+
+
+//========================================================================
+// Returns the specified attribute of the specified pixel format
+// NOTE: Do not call this unless we have found WGL_ARB_pixel_format
+//========================================================================
+
+static int getPixelFormatAttrib(int pixelFormat, int attrib)
+{
+ int value = 0;
+
+ if( !_glfwWin.GetPixelFormatAttribivARB( _glfwWin.DC, pixelFormat, 0, 1, &attrib, &value) )
+ {
+ // NOTE: We should probably handle this error somehow
+ return 0;
+ }
+
+ return value;
+}
+
+
+//========================================================================
+// Return a list of available and usable framebuffer configs
+//========================================================================
+
+static _GLFWfbconfig *getFBConfigs( unsigned int *found )
+{
+ _GLFWfbconfig *result;
+ PIXELFORMATDESCRIPTOR pfd;
+ int i, count;
+
+ *found = 0;
+
+ if( _glfwWin.has_WGL_ARB_pixel_format )
+ {
+ count = getPixelFormatAttrib( 1, WGL_NUMBER_PIXEL_FORMATS_ARB );
+ }
+ else
+ {
+ count = _glfw_DescribePixelFormat( _glfwWin.DC, 1, sizeof( PIXELFORMATDESCRIPTOR ), NULL );
+ }
+
+ if( !count )
+ {
+ fprintf( stderr, "No Win32 pixel formats available\n" );
+ return NULL;
+ }
+
+ result = (_GLFWfbconfig*) malloc( sizeof( _GLFWfbconfig ) * count );
+ if( !result )
+ {
+ fprintf(stderr, "Out of memory");
+ return NULL;
+ }
+
+ for( i = 1; i <= count; i++ )
+ {
+ if( _glfwWin.has_WGL_ARB_pixel_format )
+ {
+ // Get pixel format attributes through WGL_ARB_pixel_format
+
+ if( !getPixelFormatAttrib( i, WGL_SUPPORT_OPENGL_ARB ) ||
+ !getPixelFormatAttrib( i, WGL_DRAW_TO_WINDOW_ARB ) ||
+ !getPixelFormatAttrib( i, WGL_DOUBLE_BUFFER_ARB ) )
+ {
+ // Only consider doublebuffered OpenGL pixel formats for windows
+ continue;
+ }
+
+ if( getPixelFormatAttrib( i, WGL_PIXEL_TYPE_ARB ) != WGL_TYPE_RGBA_ARB )
+ {
+ // Only consider RGBA pixel formats
+ continue;
+ }
+
+ result[*found].redBits = getPixelFormatAttrib( i, WGL_RED_BITS_ARB );
+ result[*found].greenBits = getPixelFormatAttrib( i, WGL_GREEN_BITS_ARB );
+ result[*found].blueBits = getPixelFormatAttrib( i, WGL_BLUE_BITS_ARB );
+ result[*found].alphaBits = getPixelFormatAttrib( i, WGL_ALPHA_BITS_ARB );
+
+ result[*found].depthBits = getPixelFormatAttrib( i, WGL_DEPTH_BITS_ARB );
+ result[*found].stencilBits = getPixelFormatAttrib( i, WGL_STENCIL_BITS_ARB );
+
+ result[*found].accumRedBits = getPixelFormatAttrib( i, WGL_ACCUM_RED_BITS_ARB );
+ result[*found].accumGreenBits = getPixelFormatAttrib( i, WGL_ACCUM_GREEN_BITS_ARB );
+ result[*found].accumBlueBits = getPixelFormatAttrib( i, WGL_ACCUM_BLUE_BITS_ARB );
+ result[*found].accumAlphaBits = getPixelFormatAttrib( i, WGL_ACCUM_ALPHA_BITS_ARB );
+
+ result[*found].auxBuffers = getPixelFormatAttrib( i, WGL_AUX_BUFFERS_ARB );
+ result[*found].stereo = getPixelFormatAttrib( i, WGL_STEREO_ARB );
+
+ if( _glfwWin.has_WGL_ARB_multisample )
+ {
+ result[*found].samples = getPixelFormatAttrib( i, WGL_SAMPLES_ARB );
+ }
+ else
+ {
+ result[*found].samples = 0;
+ }
+ }
+ else
+ {
+ // Get pixel format attributes through old-fashioned PFDs
+
+ if( !_glfw_DescribePixelFormat( _glfwWin.DC, i, sizeof( PIXELFORMATDESCRIPTOR ), &pfd ) )
+ {
+ continue;
+ }
+
+ if( !( pfd.dwFlags & PFD_DRAW_TO_WINDOW ) ||
+ !( pfd.dwFlags & PFD_SUPPORT_OPENGL ) ||
+ !( pfd.dwFlags & PFD_DOUBLEBUFFER ) )
+ {
+ // Only consider doublebuffered OpenGL pixel formats for windows
+ continue;
+ }
+
+ if( !( pfd.dwFlags & PFD_GENERIC_ACCELERATED ) &&
+ ( pfd.dwFlags & PFD_GENERIC_FORMAT ) )
+ {
+ continue;
+ }
+
+ if( pfd.iPixelType != PFD_TYPE_RGBA )
+ {
+ // Only RGBA pixel formats considered
+ continue;
+ }
+
+ result[*found].redBits = pfd.cRedBits;
+ result[*found].greenBits = pfd.cGreenBits;
+ result[*found].blueBits = pfd.cBlueBits;
+ result[*found].alphaBits = pfd.cAlphaBits;
+
+ result[*found].depthBits = pfd.cDepthBits;
+ result[*found].stencilBits = pfd.cStencilBits;
+
+ result[*found].accumRedBits = pfd.cAccumRedBits;
+ result[*found].accumGreenBits = pfd.cAccumGreenBits;
+ result[*found].accumBlueBits = pfd.cAccumBlueBits;
+ result[*found].accumAlphaBits = pfd.cAccumAlphaBits;
+
+ result[*found].auxBuffers = pfd.cAuxBuffers;
+ result[*found].stereo = ( pfd.dwFlags & PFD_STEREO ) ? GL_TRUE : GL_FALSE;
+
+ // PFD pixel formats do not support FSAA
+ result[*found].samples = 0;
+ }
+
+ result[*found].platformID = i;
+
+ (*found)++;
+ }
+
+ return result;
+}
+
+
+//========================================================================
+// Creates an OpenGL context on the specified device context
+//========================================================================
+
+static HGLRC createContext( HDC dc, const _GLFWwndconfig* wndconfig, int pixelFormat )
+{
+ PIXELFORMATDESCRIPTOR pfd;
+ int flags, i = 0, attribs[7];
+
+ if( !_glfw_DescribePixelFormat( dc, pixelFormat, sizeof(pfd), &pfd ) )
+ {
+ return NULL;
+ }
+
+ if( !_glfw_SetPixelFormat( dc, pixelFormat, &pfd ) )
+ {
+ return NULL;
+ }
+
+ if( _glfwWin.has_WGL_ARB_create_context )
+ {
+ // Use the newer wglCreateContextAttribsARB
+
+ if( wndconfig->glMajor != 1 || wndconfig->glMinor != 0 )
+ {
+ // Request an explicitly versioned context
+
+ attribs[i++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
+ attribs[i++] = wndconfig->glMajor;
+ attribs[i++] = WGL_CONTEXT_MINOR_VERSION_ARB;
+ attribs[i++] = wndconfig->glMinor;
+ }
+
+ if( wndconfig->glForward || wndconfig->glDebug )
+ {
+ flags = 0;
+
+ if( wndconfig->glForward )
+ {
+ flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+ }
+
+ if( wndconfig->glDebug )
+ {
+ flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
+ }
+
+ attribs[i++] = WGL_CONTEXT_FLAGS_ARB;
+ attribs[i++] = flags;
+ }
+
+ if( wndconfig->glProfile )
+ {
+ if( wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE )
+ {
+ flags = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
+ }
+ else
+ {
+ flags = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+ }
+
+ attribs[i++] = WGL_CONTEXT_PROFILE_MASK_ARB;
+ attribs[i++] = flags;
+ }
+
+ attribs[i++] = 0;
+
+ return _glfwWin.CreateContextAttribsARB( dc, NULL, attribs );
+ }
+
+ return wglCreateContext( dc );
+}
+
+
+//========================================================================
+// Translates a Windows key to the corresponding GLFW key
+//========================================================================
+
+static int translateKey( WPARAM wParam, LPARAM lParam )
+{
+ MSG next_msg;
+ DWORD msg_time;
+ DWORD scan_code;
+
+ // Check for numeric keypad keys
+ // Note: This way we always force "NumLock = ON", which at least
+ // enables GLFW users to detect numeric keypad keys
+ int hiFlags = HIWORD( lParam );
+
+ if ( !( hiFlags & 0x100 ) )
+ {
+ switch( MapVirtualKey( hiFlags & 0xFF, 1 ) )
+ {
+ case VK_INSERT: return GLFW_KEY_KP_0;
+ case VK_END: return GLFW_KEY_KP_1;
+ case VK_DOWN: return GLFW_KEY_KP_2;
+ case VK_NEXT: return GLFW_KEY_KP_3;
+ case VK_LEFT: return GLFW_KEY_KP_4;
+ case VK_CLEAR: return GLFW_KEY_KP_5;
+ case VK_RIGHT: return GLFW_KEY_KP_6;
+ case VK_HOME: return GLFW_KEY_KP_7;
+ case VK_UP: return GLFW_KEY_KP_8;
+ case VK_PRIOR: return GLFW_KEY_KP_9;
+ case VK_DIVIDE: return GLFW_KEY_KP_DIVIDE;
+ case VK_MULTIPLY: return GLFW_KEY_KP_MULTIPLY;
+ case VK_SUBTRACT: return GLFW_KEY_KP_SUBTRACT;
+ case VK_ADD: return GLFW_KEY_KP_ADD;
+ case VK_DELETE: return GLFW_KEY_KP_DECIMAL;
+ }
+ }
+
+ // Check which key was pressed or released
+ switch( wParam )
+ {
+ // The SHIFT keys require special handling
+ case VK_SHIFT:
+ {
+ // Compare scan code for this key with that of VK_RSHIFT in
+ // order to determine which shift key was pressed (left or
+ // right)
+ scan_code = MapVirtualKey( VK_RSHIFT, 0 );
+ if( ((lParam & 0x01ff0000) >> 16) == scan_code )
+ {
+ return GLFW_KEY_RSHIFT;
+ }
+
+ return GLFW_KEY_LSHIFT;
+ }
+
+ // The CTRL keys require special handling
+ case VK_CONTROL:
+ {
+ // Is this an extended key (i.e. right key)?
+ if( lParam & 0x01000000 )
+ {
+ return GLFW_KEY_RCTRL;
+ }
+
+ // Here is a trick: "Alt Gr" sends LCTRL, then RALT. We only
+ // want the RALT message, so we try to see if the next message
+ // is a RALT message. In that case, this is a false LCTRL!
+ msg_time = GetMessageTime();
+ if( PeekMessage( &next_msg, NULL, 0, 0, PM_NOREMOVE ) )
+ {
+ if( next_msg.message == WM_KEYDOWN ||
+ next_msg.message == WM_SYSKEYDOWN )
+ {
+ if( next_msg.wParam == VK_MENU &&
+ (next_msg.lParam & 0x01000000) &&
+ next_msg.time == msg_time )
+ {
+ // Next message is a RALT down message, which
+ // means that this is NOT a proper LCTRL message!
+ return GLFW_KEY_UNKNOWN;
+ }
+ }
+ }
+
+ return GLFW_KEY_LCTRL;
+ }
+
+ // The ALT keys require special handling
+ case VK_MENU:
+ {
+ // Is this an extended key (i.e. right key)?
+ if( lParam & 0x01000000 )
+ {
+ return GLFW_KEY_RALT;
+ }
+
+ return GLFW_KEY_LALT;
+ }
+
+ // The ENTER keys require special handling
+ case VK_RETURN:
+ {
+ // Is this an extended key (i.e. right key)?
+ if( lParam & 0x01000000 )
+ {
+ return GLFW_KEY_KP_ENTER;
+ }
+
+ return GLFW_KEY_ENTER;
+ }
+
+ // Special keys (non character keys)
+ case VK_ESCAPE: return GLFW_KEY_ESC;
+ case VK_TAB: return GLFW_KEY_TAB;
+ case VK_BACK: return GLFW_KEY_BACKSPACE;
+ case VK_HOME: return GLFW_KEY_HOME;
+ case VK_END: return GLFW_KEY_END;
+ case VK_PRIOR: return GLFW_KEY_PAGEUP;
+ case VK_NEXT: return GLFW_KEY_PAGEDOWN;
+ case VK_INSERT: return GLFW_KEY_INSERT;
+ case VK_DELETE: return GLFW_KEY_DEL;
+ case VK_LEFT: return GLFW_KEY_LEFT;
+ case VK_UP: return GLFW_KEY_UP;
+ case VK_RIGHT: return GLFW_KEY_RIGHT;
+ case VK_DOWN: return GLFW_KEY_DOWN;
+ case VK_F1: return GLFW_KEY_F1;
+ case VK_F2: return GLFW_KEY_F2;
+ case VK_F3: return GLFW_KEY_F3;
+ case VK_F4: return GLFW_KEY_F4;
+ case VK_F5: return GLFW_KEY_F5;
+ case VK_F6: return GLFW_KEY_F6;
+ case VK_F7: return GLFW_KEY_F7;
+ case VK_F8: return GLFW_KEY_F8;
+ case VK_F9: return GLFW_KEY_F9;
+ case VK_F10: return GLFW_KEY_F10;
+ case VK_F11: return GLFW_KEY_F11;
+ case VK_F12: return GLFW_KEY_F12;
+ case VK_F13: return GLFW_KEY_F13;
+ case VK_F14: return GLFW_KEY_F14;
+ case VK_F15: return GLFW_KEY_F15;
+ case VK_F16: return GLFW_KEY_F16;
+ case VK_F17: return GLFW_KEY_F17;
+ case VK_F18: return GLFW_KEY_F18;
+ case VK_F19: return GLFW_KEY_F19;
+ case VK_F20: return GLFW_KEY_F20;
+ case VK_F21: return GLFW_KEY_F21;
+ case VK_F22: return GLFW_KEY_F22;
+ case VK_F23: return GLFW_KEY_F23;
+ case VK_F24: return GLFW_KEY_F24;
+ case VK_SPACE: return GLFW_KEY_SPACE;
+
+ // Numeric keypad
+ case VK_NUMPAD0: return GLFW_KEY_KP_0;
+ case VK_NUMPAD1: return GLFW_KEY_KP_1;
+ case VK_NUMPAD2: return GLFW_KEY_KP_2;
+ case VK_NUMPAD3: return GLFW_KEY_KP_3;
+ case VK_NUMPAD4: return GLFW_KEY_KP_4;
+ case VK_NUMPAD5: return GLFW_KEY_KP_5;
+ case VK_NUMPAD6: return GLFW_KEY_KP_6;
+ case VK_NUMPAD7: return GLFW_KEY_KP_7;
+ case VK_NUMPAD8: return GLFW_KEY_KP_8;
+ case VK_NUMPAD9: return GLFW_KEY_KP_9;
+ case VK_DIVIDE: return GLFW_KEY_KP_DIVIDE;
+ case VK_MULTIPLY: return GLFW_KEY_KP_MULTIPLY;
+ case VK_SUBTRACT: return GLFW_KEY_KP_SUBTRACT;
+ case VK_ADD: return GLFW_KEY_KP_ADD;
+ case VK_DECIMAL: return GLFW_KEY_KP_DECIMAL;
+ case VK_NUMLOCK: return GLFW_KEY_KP_NUM_LOCK;
+
+ case VK_CAPITAL: return GLFW_KEY_CAPS_LOCK;
+ case VK_SCROLL: return GLFW_KEY_SCROLL_LOCK;
+ case VK_PAUSE: return GLFW_KEY_PAUSE;
+
+ case VK_LWIN: return GLFW_KEY_LSUPER;
+ case VK_RWIN: return GLFW_KEY_RSUPER;
+ case VK_APPS: return GLFW_KEY_MENU;
+
+ // The rest (should be printable keys)
+ default:
+ {
+ // Convert to printable character (ISO-8859-1 or Unicode)
+ wParam = MapVirtualKey( (UINT) wParam, 2 ) & 0x0000FFFF;
+
+ // Make sure that the character is uppercase
+ if( _glfwLibrary.Sys.hasUnicode )
+ {
+ wParam = (WPARAM) CharUpperW( (LPWSTR) wParam );
+ }
+ else
+ {
+ wParam = (WPARAM) CharUpperA( (LPSTR) wParam );
+ }
+
+ // Valid ISO-8859-1 character?
+ if( (wParam >= 32 && wParam <= 126) ||
+ (wParam >= 160 && wParam <= 255) )
+ {
+ return (int) wParam;
+ }
+
+ return GLFW_KEY_UNKNOWN;
+ }
+ }
+}
+
+
+//========================================================================
+// Translates a Windows key to Unicode
+//========================================================================
+
+static void translateChar( DWORD wParam, DWORD lParam, int action )
+{
+ BYTE keyboard_state[ 256 ];
+ UCHAR char_buf[ 10 ];
+ WCHAR unicode_buf[ 10 ];
+ UINT scan_code;
+ int i, num_chars, unicode;
+
+ GetKeyboardState( keyboard_state );
+
+ // Derive scan code from lParam and action
+ scan_code = (lParam & 0x01ff0000) >> 16;
+ if( action == GLFW_RELEASE )
+ {
+ scan_code |= 0x8000000;
+ }
+
+ if( _glfwLibrary.Sys.hasUnicode )
+ {
+ num_chars = ToUnicode(
+ wParam, // virtual-key code
+ scan_code, // scan code
+ keyboard_state, // key-state array
+ unicode_buf, // buffer for translated key
+ 10, // size of translated key buffer
+ 0 // active-menu flag
+ );
+ unicode = 1;
+ }
+ else
+ {
+ // Convert to ISO-8859-1
+ num_chars = ToAscii(
+ wParam, // virtual-key code
+ scan_code, // scan code
+ keyboard_state, // key-state array
+ (LPWORD) char_buf, // buffer for translated key
+ 0 // active-menu flag
+ );
+ unicode = 0;
+ }
+
+ // Report characters
+ for( i = 0; i < num_chars; i++ )
+ {
+ // Get next character from buffer
+ if( unicode )
+ {
+ _glfwInputChar( (int) unicode_buf[ i ], action );
+ }
+ else
+ {
+ _glfwInputChar( (int) char_buf[ i ], action );
+ }
+ }
+}
+
+
+//========================================================================
+// Window callback function (handles window events)
+//========================================================================
+
+static LRESULT CALLBACK windowProc( HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam )
+{
+ int wheelDelta, iconified;
+
+ switch( uMsg )
+ {
+ // Window activate message? (iconification?)
+ case WM_ACTIVATE:
+ {
+ _glfwWin.active = LOWORD(wParam) != WA_INACTIVE ? GL_TRUE : GL_FALSE;
+
+ iconified = HIWORD(wParam) ? GL_TRUE : GL_FALSE;
+
+ // Were we deactivated/iconified?
+ if( (!_glfwWin.active || iconified) && !_glfwWin.iconified )
+ {
+ _glfwInputDeactivation();
+
+ // If we are in fullscreen mode we need to iconify
+ if( _glfwWin.opened && _glfwWin.fullscreen )
+ {
+ // Do we need to manually iconify?
+ if( !iconified )
+ {
+ // Minimize window
+ CloseWindow( _glfwWin.window );
+ iconified = GL_TRUE;
+ }
+
+ // Restore the original desktop resolution
+ ChangeDisplaySettings( NULL, CDS_FULLSCREEN );
+ }
+
+ // Unlock mouse if locked
+ if( !_glfwWin.oldMouseLockValid )
+ {
+ _glfwWin.oldMouseLock = _glfwWin.mouseLock;
+ _glfwWin.oldMouseLockValid = GL_TRUE;
+ glfwEnable( GLFW_MOUSE_CURSOR );
+ }
+ }
+ else if( _glfwWin.active || !iconified )
+ {
+ // If we are in fullscreen mode we need to maximize
+ if( _glfwWin.opened && _glfwWin.fullscreen && _glfwWin.iconified )
+ {
+ // Change display settings to the user selected mode
+ _glfwSetVideoModeMODE( _glfwWin.modeID );
+
+ // Do we need to manually restore window?
+ if( iconified )
+ {
+ // Restore window
+ OpenIcon( _glfwWin.window );
+ iconified = GL_FALSE;
+
+ // Activate window
+ ShowWindow( hWnd, SW_SHOW );
+ setForegroundWindow( _glfwWin.window );
+ SetFocus( _glfwWin.window );
+ }
+ }
+
+ // Lock mouse, if necessary
+ if( _glfwWin.oldMouseLockValid && _glfwWin.oldMouseLock )
+ {
+ glfwDisable( GLFW_MOUSE_CURSOR );
+ }
+ _glfwWin.oldMouseLockValid = GL_FALSE;
+ }
+
+ _glfwWin.iconified = iconified;
+ return 0;
+ }
+
+ case WM_SYSCOMMAND:
+ {
+ switch( wParam & 0xfff0 )
+ {
+ case SC_SCREENSAVE:
+ case SC_MONITORPOWER:
+ {
+ if( _glfwWin.fullscreen )
+ {
+ // Disallow screen saver and screen blanking if we are
+ // running in fullscreen mode
+ return 0;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // User trying to access application menu using ALT?
+ case SC_KEYMENU:
+ return 0;
+ }
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ // Translate this to WM_QUIT so that we can handle all cases in the
+ // same place
+ PostQuitMessage( 0 );
+ return 0;
+ }
+
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ {
+ _glfwInputKey( translateKey( wParam, lParam ), GLFW_PRESS );
+
+ if( _glfwWin.charCallback )
+ {
+ translateChar( (DWORD) wParam, (DWORD) lParam, GLFW_PRESS );
+ }
+ return 0;
+ }
+
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ {
+ // Special trick: release both shift keys on SHIFT up event
+ if( wParam == VK_SHIFT )
+ {
+ _glfwInputKey( GLFW_KEY_LSHIFT, GLFW_RELEASE );
+ _glfwInputKey( GLFW_KEY_RSHIFT, GLFW_RELEASE );
+ }
+ else
+ {
+ _glfwInputKey( translateKey( wParam, lParam ), GLFW_RELEASE );
+ }
+
+ if( _glfwWin.charCallback )
+ {
+ translateChar( (DWORD) wParam, (DWORD) lParam, GLFW_RELEASE );
+ }
+
+ return 0;
+ }
+
+ case WM_LBUTTONDOWN:
+ SetCapture(hWnd);
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS );
+ return 0;
+ case WM_RBUTTONDOWN:
+ SetCapture(hWnd);
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS );
+ return 0;
+ case WM_MBUTTONDOWN:
+ SetCapture(hWnd);
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS );
+ return 0;
+ case WM_XBUTTONDOWN:
+ {
+ if( HIWORD(wParam) == XBUTTON1 )
+ {
+ SetCapture(hWnd);
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_4, GLFW_PRESS );
+ }
+ else if( HIWORD(wParam) == XBUTTON2 )
+ {
+ SetCapture(hWnd);
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_5, GLFW_PRESS );
+ }
+ return 1;
+ }
+
+ case WM_LBUTTONUP:
+ ReleaseCapture();
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE );
+ return 0;
+ case WM_RBUTTONUP:
+ ReleaseCapture();
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE );
+ return 0;
+ case WM_MBUTTONUP:
+ ReleaseCapture();
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE );
+ return 0;
+ case WM_XBUTTONUP:
+ {
+ if( HIWORD(wParam) == XBUTTON1 )
+ {
+ ReleaseCapture();
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_4, GLFW_RELEASE );
+ }
+ else if( HIWORD(wParam) == XBUTTON2 )
+ {
+ ReleaseCapture();
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_5, GLFW_RELEASE );
+ }
+ return 1;
+ }
+
+ case WM_MOUSEMOVE:
+ {
+ int NewMouseX, NewMouseY;
+
+ // Get signed (!) mouse position
+ NewMouseX = (int)((short)LOWORD(lParam));
+ NewMouseY = (int)((short)HIWORD(lParam));
+
+ if( NewMouseX != _glfwInput.OldMouseX ||
+ NewMouseY != _glfwInput.OldMouseY )
+ {
+ if( _glfwWin.mouseLock )
+ {
+ _glfwInput.MousePosX += NewMouseX -
+ _glfwInput.OldMouseX;
+ _glfwInput.MousePosY += NewMouseY -
+ _glfwInput.OldMouseY;
+ }
+ else
+ {
+ _glfwInput.MousePosX = NewMouseX;
+ _glfwInput.MousePosY = NewMouseY;
+ }
+ _glfwInput.OldMouseX = NewMouseX;
+ _glfwInput.OldMouseY = NewMouseY;
+ _glfwInput.MouseMoved = GL_TRUE;
+
+ if( _glfwWin.mousePosCallback )
+ {
+ _glfwWin.mousePosCallback( _glfwInput.MousePosX,
+ _glfwInput.MousePosY );
+ }
+ }
+ return 0;
+ }
+
+ case WM_MOUSEWHEEL:
+ {
+ // WM_MOUSEWHEEL is not supported under Windows 95
+ if( _glfwLibrary.Sys.winVer != _GLFW_WIN_95 )
+ {
+ wheelDelta = (((int)wParam) >> 16) / WHEEL_DELTA;
+ _glfwInput.WheelPos += wheelDelta;
+ if( _glfwWin.mouseWheelCallback )
+ {
+ _glfwWin.mouseWheelCallback( _glfwInput.WheelPos );
+ }
+ return 0;
+ }
+ break;
+ }
+
+ case WM_SIZE:
+ {
+ _glfwWin.width = LOWORD(lParam);
+ _glfwWin.height = HIWORD(lParam);
+
+ // If the mouse is locked, update the clipping rect
+ if( _glfwWin.mouseLock )
+ {
+ RECT ClipWindowRect;
+ if( GetWindowRect( _glfwWin.window, &ClipWindowRect ) )
+ {
+ ClipCursor( &ClipWindowRect );
+ }
+ }
+
+ if( _glfwWin.windowSizeCallback )
+ {
+ _glfwWin.windowSizeCallback( LOWORD(lParam), HIWORD(lParam) );
+ }
+ return 0;
+ }
+
+ case WM_MOVE:
+ {
+ // If the mouse is locked, update the clipping rect
+ if( _glfwWin.mouseLock )
+ {
+ RECT ClipWindowRect;
+ if( GetWindowRect( _glfwWin.window, &ClipWindowRect ) )
+ {
+ ClipCursor( &ClipWindowRect );
+ }
+ }
+ return 0;
+ }
+
+ // Was the window contents damaged?
+ case WM_PAINT:
+ {
+ if( _glfwWin.windowRefreshCallback )
+ {
+ _glfwWin.windowRefreshCallback();
+ }
+ break;
+ }
+
+ case WM_DISPLAYCHANGE:
+ {
+ // TODO: Do stuff here.
+
+ break;
+ }
+ }
+
+ // Pass all unhandled messages to DefWindowProc
+ return DefWindowProc( hWnd, uMsg, wParam, lParam );
+}
+
+
+//========================================================================
+// Translate client window size to full window size (including window borders)
+//========================================================================
+
+static void getFullWindowSize( int clientWidth, int clientHeight,
+ int *fullWidth, int *fullHeight )
+{
+ RECT rect;
+
+ // Create a window rectangle
+ rect.left = (long)0;
+ rect.right = (long)clientWidth - 1;
+ rect.top = (long)0;
+ rect.bottom = (long)clientHeight - 1;
+
+ // Adjust according to window styles
+ AdjustWindowRectEx( &rect, _glfwWin.dwStyle, FALSE, _glfwWin.dwExStyle );
+
+ // Calculate width and height of full window
+ *fullWidth = rect.right - rect.left + 1;
+ *fullHeight = rect.bottom - rect.top + 1;
+}
+
+
+//========================================================================
+// Initialize WGL-specific extensions
+// This function is called once before initial context creation, i.e. before
+// any WGL extensions could be present. This is done in order to have both
+// extension variable clearing and loading in the same place, hopefully
+// decreasing the possibility of forgetting to add one without the other.
+//========================================================================
+
+static void initWGLExtensions( void )
+{
+ // This needs to include every function pointer loaded below
+ _glfwWin.SwapIntervalEXT = NULL;
+ _glfwWin.GetPixelFormatAttribivARB = NULL;
+ _glfwWin.GetExtensionsStringARB = NULL;
+ _glfwWin.GetExtensionsStringEXT = NULL;
+ _glfwWin.CreateContextAttribsARB = NULL;
+
+ // This needs to include every extension used below except for
+ // WGL_ARB_extensions_string and WGL_EXT_extensions_string
+ _glfwWin.has_WGL_EXT_swap_control = GL_FALSE;
+ _glfwWin.has_WGL_ARB_pixel_format = GL_FALSE;
+ _glfwWin.has_WGL_ARB_multisample = GL_FALSE;
+ _glfwWin.has_WGL_ARB_create_context = GL_FALSE;
+
+ _glfwWin.GetExtensionsStringEXT = (WGLGETEXTENSIONSSTRINGEXT_T)
+ wglGetProcAddress( "wglGetExtensionsStringEXT" );
+ if( !_glfwWin.GetExtensionsStringEXT )
+ {
+ _glfwWin.GetExtensionsStringARB = (WGLGETEXTENSIONSSTRINGARB_T)
+ wglGetProcAddress( "wglGetExtensionsStringARB" );
+ if( !_glfwWin.GetExtensionsStringARB )
+ {
+ return;
+ }
+ }
+
+ if( _glfwPlatformExtensionSupported( "WGL_ARB_multisample" ) )
+ {
+ _glfwWin.has_WGL_ARB_multisample = GL_TRUE;
+ }
+
+ if( _glfwPlatformExtensionSupported( "WGL_ARB_create_context" ) )
+ {
+ _glfwWin.has_WGL_ARB_create_context = GL_TRUE;
+ _glfwWin.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
+ wglGetProcAddress( "wglCreateContextAttribsARB" );
+ }
+
+ if( _glfwPlatformExtensionSupported( "WGL_EXT_swap_control" ) )
+ {
+ _glfwWin.has_WGL_EXT_swap_control = GL_TRUE;
+ _glfwWin.SwapIntervalEXT = (WGLSWAPINTERVALEXT_T)
+ wglGetProcAddress( "wglSwapIntervalEXT" );
+ }
+
+ if( _glfwPlatformExtensionSupported( "WGL_ARB_pixel_format" ) )
+ {
+ _glfwWin.has_WGL_ARB_pixel_format = GL_TRUE;
+ _glfwWin.GetPixelFormatAttribivARB = (WGLGETPIXELFORMATATTRIBIVARB_T)
+ wglGetProcAddress( "wglGetPixelFormatAttribivARB" );
+ }
+}
+
+
+//========================================================================
+// Registers the GLFW window class
+//========================================================================
+
+static ATOM registerWindowClass( void )
+{
+ WNDCLASS wc;
+
+ // Set window class parameters
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw on...
+ wc.lpfnWndProc = (WNDPROC)windowProc; // Message handler
+ wc.cbClsExtra = 0; // No extra class data
+ wc.cbWndExtra = 0; // No extra window data
+ wc.hInstance = _glfwLibrary.instance; // Set instance
+ wc.hCursor = LoadCursor( NULL, IDC_ARROW ); // Load arrow pointer
+ wc.hbrBackground = NULL; // No background
+ wc.lpszMenuName = NULL; // No menu
+ wc.lpszClassName = _GLFW_WNDCLASSNAME; // Set class name
+
+ // Load user-provided icon if available
+ wc.hIcon = LoadIcon( _glfwLibrary.instance, "GLFW_ICON" );
+ if( !wc.hIcon )
+ {
+ // Load default icon
+ wc.hIcon = LoadIcon( NULL, IDI_WINLOGO );
+ }
+
+ return RegisterClass( &wc );
+}
+
+
+//========================================================================
+// Returns the closest matching pixel format, or zero on error
+//========================================================================
+
+static int choosePixelFormat( const _GLFWfbconfig *fbconfig )
+{
+ unsigned int fbcount;
+ int pixelFormat;
+ _GLFWfbconfig *fbconfigs;
+ const _GLFWfbconfig *closest;
+
+ fbconfigs = getFBConfigs( &fbcount );
+ if( !fbconfigs )
+ {
+ fprintf( stderr, "Failed to find any usable GLFWFBConfigs\n" );
+ return 0;
+ }
+
+ closest = _glfwChooseFBConfig( fbconfig, fbconfigs, fbcount );
+ if( !closest )
+ {
+ fprintf( stderr, "Failed to select a GLFWFBConfig from the alternatives\n" );
+ free( fbconfigs );
+ return 0;
+ }
+
+ pixelFormat = (int) closest->platformID;
+
+ free( fbconfigs );
+ fbconfigs = NULL;
+ closest = NULL;
+
+ return pixelFormat;
+}
+
+
+//========================================================================
+// Creates the GLFW window and rendering context
+//========================================================================
+
+static int createWindow( const _GLFWwndconfig *wndconfig,
+ const _GLFWfbconfig *fbconfig )
+{
+ DWORD dwStyle, dwExStyle;
+ int pixelFormat, fullWidth, fullHeight;
+ RECT wa;
+ POINT pos;
+
+ _glfwWin.DC = NULL;
+ _glfwWin.context = NULL;
+ _glfwWin.window = NULL;
+
+ // Set common window styles
+ dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
+ dwExStyle = WS_EX_APPWINDOW;
+
+ // Set window style, depending on fullscreen mode
+ if( _glfwWin.fullscreen )
+ {
+ dwStyle |= WS_POPUP;
+
+ // Here's a trick for helping us getting window focus
+ // (SetForegroundWindow doesn't work properly under
+ // Win98/ME/2K/.NET/+)
+ /*
+ if( _glfwLibrary.Sys.WinVer != _GLFW_WIN_95 &&
+ _glfwLibrary.Sys.WinVer != _GLFW_WIN_NT4 &&
+ _glfwLibrary.Sys.WinVer != _GLFW_WIN_XP )
+ {
+ dwStyle |= WS_MINIMIZE;
+ }
+ */
+ }
+ else
+ {
+ dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
+
+ if( !wndconfig->windowNoResize )
+ {
+ dwStyle |= ( WS_MAXIMIZEBOX | WS_SIZEBOX );
+ dwExStyle |= WS_EX_WINDOWEDGE;
+ }
+ }
+
+ // Remember window styles (used by getFullWindowSize)
+ _glfwWin.dwStyle = dwStyle;
+ _glfwWin.dwExStyle = dwExStyle;
+
+ // Adjust window size for frame and title bar
+ getFullWindowSize( _glfwWin.width, _glfwWin.height, &fullWidth, &fullHeight );
+
+ // Adjust window position to working area (e.g. if the task bar is at
+ // the top of the display). Fullscreen windows are always opened in
+ // the upper left corner regardless of the desktop working area.
+ if( _glfwWin.fullscreen )
+ {
+ wa.left = wa.top = 0;
+ }
+ else
+ {
+ SystemParametersInfo( SPI_GETWORKAREA, 0, &wa, 0 );
+ }
+
+ _glfwWin.window = CreateWindowEx( _glfwWin.dwExStyle, // Extended style
+ _GLFW_WNDCLASSNAME, // Class name
+ "GLFW Window", // Window title
+ _glfwWin.dwStyle, // Defined window style
+ wa.left, wa.top, // Window position
+ fullWidth, // Decorated window width
+ fullHeight, // Decorated window height
+ NULL, // No parent window
+ NULL, // No menu
+ _glfwLibrary.instance, // Instance
+ NULL ); // Nothing to WM_CREATE
+
+ if( !_glfwWin.window )
+ {
+ fprintf( stderr, "Unable to create Win32 window\n" );
+ return GL_FALSE;
+ }
+
+ _glfwWin.DC = GetDC( _glfwWin.window );
+ if( !_glfwWin.DC )
+ {
+ fprintf( stderr, "Unable to retrieve GLFW window DC\n" );
+ return GL_FALSE;
+ }
+
+ pixelFormat = choosePixelFormat( fbconfig );
+ if( !pixelFormat )
+ {
+ fprintf( stderr, "Unable to find a usable pixel format\n" );
+ return GL_FALSE;
+ }
+
+ _glfwWin.context = createContext( _glfwWin.DC, wndconfig, pixelFormat );
+ if( !_glfwWin.context )
+ {
+ fprintf( stderr, "Unable to create OpenGL context\n" );
+ return GL_FALSE;
+ }
+
+ if( !wglMakeCurrent( _glfwWin.DC, _glfwWin.context ) )
+ {
+ fprintf( stderr, "Unable to make OpenGL context current\n" );
+ return GL_FALSE;
+ }
+
+ initWGLExtensions();
+
+ // Initialize mouse position data
+ GetCursorPos( &pos );
+ ScreenToClient( _glfwWin.window, &pos );
+ _glfwInput.OldMouseX = _glfwInput.MousePosX = pos.x;
+ _glfwInput.OldMouseY = _glfwInput.MousePosY = pos.y;
+
+ return GL_TRUE;
+}
+
+
+//========================================================================
+// Destroys the GLFW window and rendering context
+//========================================================================
+
+static void destroyWindow( void )
+{
+ if( _glfwWin.context )
+ {
+ wglMakeCurrent( NULL, NULL );
+ wglDeleteContext( _glfwWin.context );
+ _glfwWin.context = NULL;
+ }
+
+ if( _glfwWin.DC )
+ {
+ ReleaseDC( _glfwWin.window, _glfwWin.DC );
+ _glfwWin.DC = NULL;
+ }
+
+ if( _glfwWin.window )
+ {
+ if( _glfwLibrary.Sys.winVer <= _GLFW_WIN_NT4 )
+ {
+ // Note: Hiding the window first fixes an annoying W98/NT4
+ // remaining icon bug for fullscreen displays
+ ShowWindow( _glfwWin.window, SW_HIDE );
+ }
+
+ DestroyWindow( _glfwWin.window );
+ _glfwWin.window = NULL;
+ }
+}
+
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Here is where the window is created, and the OpenGL rendering context is
+// created
+//========================================================================
+
+int _glfwPlatformOpenWindow( int width, int height,
+ const _GLFWwndconfig *wndconfig,
+ const _GLFWfbconfig *fbconfig )
+{
+ GLboolean recreateContext = GL_FALSE;
+
+ // Clear platform specific GLFW window state
+ _glfwWin.classAtom = 0;
+ _glfwWin.oldMouseLockValid = GL_FALSE;
+
+ _glfwWin.desiredRefreshRate = wndconfig->refreshRate;
+
+ _glfwWin.classAtom = registerWindowClass();
+ if( !_glfwWin.classAtom )
+ {
+ fprintf( stderr, "Failed to register GLFW window class\n" );
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ if( _glfwWin.fullscreen )
+ {
+ _glfwSetVideoMode( &_glfwWin.width, &_glfwWin.height,
+ fbconfig->redBits, fbconfig->greenBits, fbconfig->blueBits,
+ wndconfig->refreshRate );
+ }
+
+ initWGLExtensions();
+
+ if( !createWindow( wndconfig, fbconfig ) )
+ {
+ fprintf( stderr, "Failed to create GLFW window\n" );
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ if( wndconfig->glMajor > 2 )
+ {
+ if( !_glfwWin.has_WGL_ARB_create_context )
+ {
+ fprintf( stderr, "OpenGL 3.0+ is not supported\n" );
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ recreateContext = GL_TRUE;
+ }
+
+ if( fbconfig->samples > 0 )
+ {
+ // We want FSAA, but can we get it?
+ // FSAA is not a hard constraint, so otherwise we just don't care
+
+ if( _glfwWin.has_WGL_ARB_multisample && _glfwWin.has_WGL_ARB_pixel_format )
+ {
+ // We appear to have both the FSAA extension and the means to ask for it
+ recreateContext = GL_TRUE;
+ }
+ }
+
+ if( recreateContext )
+ {
+ // Some window hints require us to re-create the context using WGL
+ // extensions retrieved through the current context, as we cannot check
+ // for WGL extensions or retrieve WGL entry points before we have a
+ // current context (actually until we have implicitly loaded the ICD)
+
+ // Yes, this is strange, and yes, this is the proper way on Win32
+
+ // As Windows only allows you to set the pixel format once for a
+ // window, we need to destroy the current window and create a new one
+ // to be able to use the new pixel format
+
+ // Technically, it may be possible to keep the old window around if
+ // we're just creating an OpenGL 3.0+ context with the same pixel
+ // format, but it's not worth the potential compatibility problems
+
+ destroyWindow();
+
+ if( !createWindow( wndconfig, fbconfig ) )
+ {
+ fprintf( stderr, "Unable to re-create GLFW window\n" );
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+ }
+
+ if( _glfwWin.fullscreen )
+ {
+ // Place the window above all topmost windows
+ SetWindowPos( _glfwWin.window, HWND_TOPMOST, 0,0,0,0,
+ SWP_NOMOVE | SWP_NOSIZE );
+ }
+
+ setForegroundWindow( _glfwWin.window );
+ SetFocus( _glfwWin.window );
+
+ return GL_TRUE;
+}
+
+
+//========================================================================
+// Properly kill the window / video display
+//========================================================================
+
+void _glfwPlatformCloseWindow( void )
+{
+ destroyWindow();
+
+ if( _glfwWin.classAtom )
+ {
+ UnregisterClass( _GLFW_WNDCLASSNAME, _glfwLibrary.instance );
+ _glfwWin.classAtom = 0;
+ }
+
+ if( _glfwWin.fullscreen )
+ {
+ // Restore original desktop resolution
+ ChangeDisplaySettings( NULL, CDS_FULLSCREEN );
+ }
+}
+
+
+//========================================================================
+// Set the window title
+//========================================================================
+
+void _glfwPlatformSetWindowTitle( const char *title )
+{
+ (void) SetWindowText( _glfwWin.window, title );
+}
+
+
+//========================================================================
+// Set the window size.
+//========================================================================
+
+void _glfwPlatformSetWindowSize( int width, int height )
+{
+ int bpp, mode = 0, refresh;
+ int sizechanged = GL_FALSE;
+ GLint drawbuffer;
+ GLfloat clearcolor[4];
+
+ if( _glfwWin.fullscreen )
+ {
+ // Get some info about the current mode
+
+ DEVMODE dm;
+
+ // Get current BPP settings
+ dm.dmSize = sizeof( DEVMODE );
+ if( EnumDisplaySettings( NULL, _glfwWin.modeID, &dm ) )
+ {
+ // Get bpp
+ bpp = dm.dmBitsPerPel;
+
+ // Get closest match for target video mode
+ refresh = _glfwWin.desiredRefreshRate;
+ mode = _glfwGetClosestVideoModeBPP( &width, &height, &bpp,
+ &refresh );
+ }
+ else
+ {
+ mode = _glfwWin.modeID;
+ }
+ }
+ else
+ {
+ // If we are in windowed mode, adjust the window size to
+ // compensate for window decorations
+ getFullWindowSize( width, height, &width, &height );
+ }
+
+ // Change window size before changing fullscreen mode?
+ if( _glfwWin.fullscreen && (width > _glfwWin.width) )
+ {
+ SetWindowPos( _glfwWin.window, HWND_TOP, 0, 0, width, height,
+ SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER );
+ sizechanged = GL_TRUE;
+ }
+
+ // Change fullscreen video mode?
+ if( _glfwWin.fullscreen && mode != _glfwWin.modeID )
+ {
+ _glfwSetVideoModeMODE( mode );
+
+ // Clear the front buffer to black (avoid ugly desktop remains in
+ // our OpenGL window)
+ glGetIntegerv( GL_DRAW_BUFFER, &drawbuffer );
+ glGetFloatv( GL_COLOR_CLEAR_VALUE, clearcolor );
+ glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
+ glClear( GL_COLOR_BUFFER_BIT );
+ if( drawbuffer == GL_BACK )
+ {
+ _glfw_SwapBuffers( _glfwWin.DC );
+ }
+ glClearColor( clearcolor[0], clearcolor[1], clearcolor[2],
+ clearcolor[3] );
+ }
+
+ // Set window size (if not already changed)
+ if( !sizechanged )
+ {
+ SetWindowPos( _glfwWin.window, HWND_TOP, 0, 0, width, height,
+ SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER );
+ }
+}
+
+
+//========================================================================
+// Set the window position
+//========================================================================
+
+void _glfwPlatformSetWindowPos( int x, int y )
+{
+ (void) SetWindowPos( _glfwWin.window, HWND_TOP, x, y, 0, 0,
+ SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOZORDER );
+}
+
+
+//========================================================================
+// Window iconification
+//========================================================================
+
+void _glfwPlatformIconifyWindow( void )
+{
+ // Iconify window
+ CloseWindow( _glfwWin.window );
+ _glfwWin.iconified = GL_TRUE;
+
+ // If we are in fullscreen mode we need to change video modes
+ if( _glfwWin.fullscreen )
+ {
+ // Change display settings to the desktop resolution
+ ChangeDisplaySettings( NULL, CDS_FULLSCREEN );
+ }
+
+ // Unlock mouse
+ if( !_glfwWin.oldMouseLockValid )
+ {
+ _glfwWin.oldMouseLock = _glfwWin.mouseLock;
+ _glfwWin.oldMouseLockValid = GL_TRUE;
+ glfwEnable( GLFW_MOUSE_CURSOR );
+ }
+}
+
+
+//========================================================================
+// Window un-iconification
+//========================================================================
+
+void _glfwPlatformRestoreWindow( void )
+{
+ // If we are in fullscreen mode we need to change video modes
+ if( _glfwWin.fullscreen )
+ {
+ // Change display settings to the user selected mode
+ _glfwSetVideoModeMODE( _glfwWin.modeID );
+ }
+
+ // Un-iconify window
+ OpenIcon( _glfwWin.window );
+
+ // Make sure that our window ends up on top of things
+ ShowWindow( _glfwWin.window, SW_SHOW );
+ setForegroundWindow( _glfwWin.window );
+ SetFocus( _glfwWin.window );
+
+ // Window is no longer iconified
+ _glfwWin.iconified = GL_FALSE;
+
+ // Lock mouse, if necessary
+ if( _glfwWin.oldMouseLockValid && _glfwWin.oldMouseLock )
+ {
+ glfwDisable( GLFW_MOUSE_CURSOR );
+ }
+ _glfwWin.oldMouseLockValid = GL_FALSE;
+}
+
+
+//========================================================================
+// Swap buffers (double-buffering)
+//========================================================================
+
+void _glfwPlatformSwapBuffers( void )
+{
+ _glfw_SwapBuffers( _glfwWin.DC );
+}
+
+
+//========================================================================
+// Set double buffering swap interval
+//========================================================================
+
+void _glfwPlatformSwapInterval( int interval )
+{
+ if( _glfwWin.has_WGL_EXT_swap_control )
+ {
+ _glfwWin.SwapIntervalEXT( interval );
+ }
+}
+
+
+//========================================================================
+// Write back window parameters into GLFW window structure
+//========================================================================
+
+void _glfwPlatformRefreshWindowParams( void )
+{
+ PIXELFORMATDESCRIPTOR pfd;
+ DEVMODE dm;
+ int pixelFormat, mode;
+
+ // Obtain a detailed description of current pixel format
+ pixelFormat = _glfw_GetPixelFormat( _glfwWin.DC );
+
+ if( _glfwWin.has_WGL_ARB_pixel_format )
+ {
+ if( getPixelFormatAttrib( pixelFormat, WGL_ACCELERATION_ARB ) !=
+ WGL_NO_ACCELERATION_ARB )
+ {
+ _glfwWin.accelerated = GL_TRUE;
+ }
+ else
+ {
+ _glfwWin.accelerated = GL_FALSE;
+ }
+
+ _glfwWin.redBits = getPixelFormatAttrib( pixelFormat, WGL_RED_BITS_ARB );
+ _glfwWin.greenBits = getPixelFormatAttrib( pixelFormat, WGL_GREEN_BITS_ARB );
+ _glfwWin.blueBits = getPixelFormatAttrib( pixelFormat, WGL_BLUE_BITS_ARB );
+
+ _glfwWin.alphaBits = getPixelFormatAttrib( pixelFormat, WGL_ALPHA_BITS_ARB );
+ _glfwWin.depthBits = getPixelFormatAttrib( pixelFormat, WGL_DEPTH_BITS_ARB );
+ _glfwWin.stencilBits = getPixelFormatAttrib( pixelFormat, WGL_STENCIL_BITS_ARB );
+
+ _glfwWin.accumRedBits = getPixelFormatAttrib( pixelFormat, WGL_ACCUM_RED_BITS_ARB );
+ _glfwWin.accumGreenBits = getPixelFormatAttrib( pixelFormat, WGL_ACCUM_GREEN_BITS_ARB );
+ _glfwWin.accumBlueBits = getPixelFormatAttrib( pixelFormat, WGL_ACCUM_BLUE_BITS_ARB );
+ _glfwWin.accumAlphaBits = getPixelFormatAttrib( pixelFormat, WGL_ACCUM_ALPHA_BITS_ARB );
+
+ _glfwWin.auxBuffers = getPixelFormatAttrib( pixelFormat, WGL_AUX_BUFFERS_ARB );
+ _glfwWin.stereo = getPixelFormatAttrib( pixelFormat, WGL_STEREO_ARB ) ? GL_TRUE : GL_FALSE;
+
+ if( _glfwWin.has_WGL_ARB_multisample )
+ {
+ _glfwWin.samples = getPixelFormatAttrib( pixelFormat, WGL_SAMPLES_ARB );
+ // Should we force 1 to 0 here for consistency, or keep 1 for transparency?
+ }
+ else
+ {
+ _glfwWin.samples = 0;
+ }
+ }
+ else
+ {
+ _glfw_DescribePixelFormat( _glfwWin.DC, pixelFormat,
+ sizeof(PIXELFORMATDESCRIPTOR), &pfd );
+
+ // Is current OpenGL context accelerated?
+ _glfwWin.accelerated = (pfd.dwFlags & PFD_GENERIC_ACCELERATED) ||
+ !(pfd.dwFlags & PFD_GENERIC_FORMAT) ? 1 : 0;
+
+ // "Standard" window parameters
+ _glfwWin.redBits = pfd.cRedBits;
+ _glfwWin.greenBits = pfd.cGreenBits;
+ _glfwWin.blueBits = pfd.cBlueBits;
+ _glfwWin.alphaBits = pfd.cAlphaBits;
+ _glfwWin.depthBits = pfd.cDepthBits;
+ _glfwWin.stencilBits = pfd.cStencilBits;
+ _glfwWin.accumRedBits = pfd.cAccumRedBits;
+ _glfwWin.accumGreenBits = pfd.cAccumGreenBits;
+ _glfwWin.accumBlueBits = pfd.cAccumBlueBits;
+ _glfwWin.accumAlphaBits = pfd.cAccumAlphaBits;
+ _glfwWin.auxBuffers = pfd.cAuxBuffers;
+ _glfwWin.stereo = (pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE;
+
+ // If we don't have WGL_ARB_pixel_format then we can't have created a
+ // multisampling context, so it's safe to hardcode zero here
+ _glfwWin.samples = 0;
+ }
+
+ // Get refresh rate
+ mode = _glfwWin.fullscreen ? _glfwWin.modeID : ENUM_CURRENT_SETTINGS;
+ dm.dmSize = sizeof( DEVMODE );
+
+ if( EnumDisplaySettings( NULL, mode, &dm ) )
+ {
+ _glfwWin.refreshRate = dm.dmDisplayFrequency;
+ if( _glfwWin.refreshRate <= 1 )
+ {
+ _glfwWin.refreshRate = 0;
+ }
+ }
+ else
+ {
+ _glfwWin.refreshRate = 0;
+ }
+}
+
+
+//========================================================================
+// Poll for new window and input events
+//========================================================================
+
+void _glfwPlatformPollEvents( void )
+{
+ MSG msg;
+ int winclosed = GL_FALSE;
+
+ // Flag: mouse was not moved (will be changed by _glfwGetNextEvent if
+ // there was a mouse move event)
+ _glfwInput.MouseMoved = GL_FALSE;
+ if( _glfwWin.mouseLock )
+ {
+ _glfwInput.OldMouseX = _glfwWin.width/2;
+ _glfwInput.OldMouseY = _glfwWin.height/2;
+ }
+ else
+ {
+ _glfwInput.OldMouseX = _glfwInput.MousePosX;
+ _glfwInput.OldMouseY = _glfwInput.MousePosY;
+ }
+
+ // Check for new window messages
+ while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
+ {
+ switch( msg.message )
+ {
+ // QUIT-message (from close window)?
+ case WM_QUIT:
+ winclosed = GL_TRUE;
+ break;
+
+ // Ok, send it to the window message handler
+ default:
+ DispatchMessage( &msg );
+ break;
+ }
+ }
+
+ // LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix)
+ // This is the only async event handling in GLFW, but it solves some
+ // nasty problems.
+ // Caveat: Does not work under Win 9x/ME.
+ if( _glfwLibrary.Sys.winVer >= _GLFW_WIN_NT4 )
+ {
+ int lshift_down, rshift_down;
+
+ // Get current state of left and right shift keys
+ lshift_down = (GetAsyncKeyState( VK_LSHIFT ) >> 15) & 1;
+ rshift_down = (GetAsyncKeyState( VK_RSHIFT ) >> 15) & 1;
+
+ // See if this differs from our belief of what has happened
+ // (we only have to check for lost key up events)
+ if( !lshift_down && _glfwInput.Key[ GLFW_KEY_LSHIFT ] == 1 )
+ {
+ _glfwInputKey( GLFW_KEY_LSHIFT, GLFW_RELEASE );
+ }
+ if( !rshift_down && _glfwInput.Key[ GLFW_KEY_RSHIFT ] == 1 )
+ {
+ _glfwInputKey( GLFW_KEY_RSHIFT, GLFW_RELEASE );
+ }
+ }
+
+ // Did we have mouse movement in locked cursor mode?
+ if( _glfwInput.MouseMoved && _glfwWin.mouseLock )
+ {
+ _glfwPlatformSetMouseCursorPos( _glfwWin.width / 2,
+ _glfwWin.height / 2 );
+ }
+
+ // Was there a window close request?
+ if( winclosed && _glfwWin.windowCloseCallback )
+ {
+ // Check if the program wants us to close the window
+ winclosed = _glfwWin.windowCloseCallback();
+ }
+ if( winclosed )
+ {
+ glfwCloseWindow();
+ }
+}
+
+
+//========================================================================
+// _glfwPlatformWaitEvents() - Wait for new window and input events
+//========================================================================
+
+void _glfwPlatformWaitEvents( void )
+{
+ WaitMessage();
+
+ _glfwPlatformPollEvents();
+}
+
+
+//========================================================================
+// Hide mouse cursor (lock it)
+//========================================================================
+
+void _glfwPlatformHideMouseCursor( void )
+{
+ RECT ClipWindowRect;
+
+ ShowCursor( FALSE );
+
+ // Clip cursor to the window
+ if( GetWindowRect( _glfwWin.window, &ClipWindowRect ) )
+ {
+ ClipCursor( &ClipWindowRect );
+ }
+
+ // Capture cursor to user window
+ SetCapture( _glfwWin.window );
+}
+
+
+//========================================================================
+// Show mouse cursor (unlock it)
+//========================================================================
+
+void _glfwPlatformShowMouseCursor( void )
+{
+ // Un-capture cursor
+ ReleaseCapture();
+
+ // Release the cursor from the window
+ ClipCursor( NULL );
+
+ ShowCursor( TRUE );
+}
+
+
+//========================================================================
+// Set physical mouse cursor position
+//========================================================================
+
+void _glfwPlatformSetMouseCursorPos( int x, int y )
+{
+ POINT pos;
+
+ // Convert client coordinates to screen coordinates
+ pos.x = x;
+ pos.y = y;
+ ClientToScreen( _glfwWin.window, &pos );
+
+ SetCursorPos( pos.x, pos.y );
+}
+
diff --git a/lib/window.c b/lib/window.c
new file mode 100644
index 00000000..cc6adcd9
--- /dev/null
+++ b/lib/window.c
@@ -0,0 +1,1030 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: Any
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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
+
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+static int Max(int a, int b)
+{
+ return (a > b) ? a : b;
+}
+
+//========================================================================
+// Clear all open window hints
+//========================================================================
+
+void _glfwClearWindowHints( void )
+{
+ memset( &_glfwLibrary.hints, 0, sizeof( _glfwLibrary.hints ) );
+ _glfwLibrary.hints.glMajor = 1;
+}
+
+
+//========================================================================
+// Handle the input tracking part of window deactivation
+//========================================================================
+
+void _glfwInputDeactivation( void )
+{
+ int i;
+
+ // Release all keyboard keys
+ for( i = 0; i <= GLFW_KEY_LAST; i ++ )
+ {
+ if( _glfwInput.Key[ i ] == GLFW_PRESS )
+ {
+ _glfwInputKey( i, GLFW_RELEASE );
+ }
+ }
+
+ // Release all mouse buttons
+ for( i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i ++ )
+ {
+ if( _glfwInput.MouseButton[ i ] == GLFW_PRESS )
+ {
+ _glfwInputMouseClick( i, GLFW_RELEASE );
+ }
+ }
+}
+
+
+//========================================================================
+// _glfwClearInput() - Clear all input state
+//========================================================================
+
+void _glfwClearInput( void )
+{
+ int i;
+
+ // Release all keyboard keys
+ for( i = 0; i <= GLFW_KEY_LAST; i ++ )
+ {
+ _glfwInput.Key[ i ] = GLFW_RELEASE;
+ }
+
+ // Clear last character
+ _glfwInput.LastChar = 0;
+
+ // Release all mouse buttons
+ for( i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i ++ )
+ {
+ _glfwInput.MouseButton[ i ] = GLFW_RELEASE;
+ }
+
+ // Set mouse position to (0,0)
+ _glfwInput.MousePosX = 0;
+ _glfwInput.MousePosY = 0;
+
+ // Set mouse wheel position to 0
+ _glfwInput.WheelPos = 0;
+
+ // The default is to use non sticky keys and mouse buttons
+ _glfwInput.StickyKeys = GL_FALSE;
+ _glfwInput.StickyMouseButtons = GL_FALSE;
+
+ // The default is to disable key repeat
+ _glfwInput.KeyRepeat = GL_FALSE;
+}
+
+
+//========================================================================
+// _glfwInputKey() - Register keyboard activity
+//========================================================================
+
+void _glfwInputKey( int key, int action )
+{
+ int keyrepeat = 0;
+
+ if( key < 0 || key > GLFW_KEY_LAST )
+ {
+ return;
+ }
+
+ // Are we trying to release an already released key?
+ if( action == GLFW_RELEASE && _glfwInput.Key[ key ] != GLFW_PRESS )
+ {
+ return;
+ }
+
+ // Register key action
+ if( action == GLFW_RELEASE && _glfwInput.StickyKeys )
+ {
+ _glfwInput.Key[ key ] = GLFW_STICK;
+ }
+ else
+ {
+ keyrepeat = (_glfwInput.Key[ key ] == GLFW_PRESS) &&
+ (action == GLFW_PRESS);
+ _glfwInput.Key[ key ] = (char) action;
+ }
+
+ // Call user callback function
+ if( _glfwWin.keyCallback && (_glfwInput.KeyRepeat || !keyrepeat) )
+ {
+ _glfwWin.keyCallback( key, action );
+ }
+}
+
+
+//========================================================================
+// Register (keyboard) character activity
+//========================================================================
+
+void _glfwInputChar( int character, int action )
+{
+ int keyrepeat = 0;
+
+ // Valid Unicode (ISO 10646) character?
+ if( !( (character >= 32 && character <= 126) || character >= 160 ) )
+ {
+ return;
+ }
+
+ // Is this a key repeat?
+ if( action == GLFW_PRESS && _glfwInput.LastChar == character )
+ {
+ keyrepeat = 1;
+ }
+
+ // Store this character as last character (or clear it, if released)
+ if( action == GLFW_PRESS )
+ {
+ _glfwInput.LastChar = character;
+ }
+ else
+ {
+ _glfwInput.LastChar = 0;
+ }
+
+ if( action != GLFW_PRESS )
+ {
+ // This intentionally breaks release notifications for Unicode
+ // characters, partly to see if anyone cares but mostly because it's
+ // a nonsensical concept to begin with
+ //
+ // It will remain broken either until its removal in the 3.0 API or
+ // until someone explains, in a way that makes sense to people outside
+ // the US and Scandinavia, what "Unicode character up" actually means
+ //
+ // If what you want is "physical key up" then you should be using the
+ // key functions and/or the key callback, NOT the Unicode input
+ //
+ // However, if your particular application uses this misfeature for...
+ // something, you can re-enable it by removing this if-statement
+ return;
+ }
+
+ if( _glfwWin.charCallback && (_glfwInput.KeyRepeat || !keyrepeat) )
+ {
+ _glfwWin.charCallback( character, action );
+ }
+}
+
+
+//========================================================================
+// _glfwInputMouseClick() - Register mouse button clicks
+//========================================================================
+
+void _glfwInputMouseClick( int button, int action )
+{
+ if( button >= 0 && button <= GLFW_MOUSE_BUTTON_LAST )
+ {
+ // Register mouse button action
+ if( action == GLFW_RELEASE && _glfwInput.StickyMouseButtons )
+ {
+ _glfwInput.MouseButton[ button ] = GLFW_STICK;
+ }
+ else
+ {
+ _glfwInput.MouseButton[ button ] = (char) action;
+ }
+
+ // Call user callback function
+ if( _glfwWin.mouseButtonCallback )
+ {
+ _glfwWin.mouseButtonCallback( button, action );
+ }
+ }
+}
+
+
+//========================================================================
+// Return the available framebuffer config closest to the desired values
+// This is based on the manual GLX Visual selection from 2.6
+//========================================================================
+
+const _GLFWfbconfig *_glfwChooseFBConfig( const _GLFWfbconfig *desired,
+ const _GLFWfbconfig *alternatives,
+ unsigned int count )
+{
+ unsigned int i;
+ unsigned int missing, leastMissing = UINT_MAX;
+ unsigned int colorDiff, leastColorDiff = UINT_MAX;
+ unsigned int extraDiff, leastExtraDiff = UINT_MAX;
+ GLboolean desiresColor = GL_FALSE;
+ const _GLFWfbconfig *current;
+ const _GLFWfbconfig *closest = NULL;
+
+ // Cache some long-winded preferences
+
+ if( desired->redBits || desired->greenBits || desired->blueBits ||
+ desired->alphaBits )
+ {
+ desiresColor = GL_TRUE;
+ }
+
+ for( i = 0; i < count; i++ )
+ {
+ current = alternatives + i;
+
+ if( desired->stereo > 0 && current->stereo == 0 )
+ {
+ // Stereo is a hard constraint
+ continue;
+ }
+
+ // Count number of missing buffers
+ {
+ missing = 0;
+
+ if( desired->alphaBits > 0 && current->alphaBits == 0 )
+ {
+ missing++;
+ }
+
+ if( desired->depthBits > 0 && current->depthBits == 0 )
+ {
+ missing++;
+ }
+
+ if( desired->stencilBits > 0 && current->stencilBits == 0 )
+ {
+ missing++;
+ }
+
+ if( desired->auxBuffers > 0 && current->auxBuffers < desired->auxBuffers )
+ {
+ missing += desired->auxBuffers - current->auxBuffers;
+ }
+
+ if( desired->samples > 0 && current->samples == 0 )
+ {
+ // Technically, several multisampling buffers could be
+ // involved, but that's a lower level implementation detail and
+ // not important to us here, so we count them as one
+ missing++;
+ }
+ }
+
+ // These polynomials make many small channel size differences matter
+ // less than one large channel size difference
+
+ // Calculate color channel size difference value
+ {
+ colorDiff = 0;
+
+ if ( desired->redBits > 0 )
+ {
+ colorDiff += ( desired->redBits - current->redBits ) *
+ ( desired->redBits - current->redBits );
+ }
+
+ if ( desired->greenBits > 0 )
+ {
+ colorDiff += ( desired->greenBits - current->greenBits ) *
+ ( desired->greenBits - current->greenBits );
+ }
+
+ if ( desired->blueBits > 0 )
+ {
+ colorDiff += ( desired->blueBits - current->blueBits ) *
+ ( desired->blueBits - current->blueBits );
+ }
+ }
+
+ // Calculate non-color channel size difference value
+ {
+ extraDiff = 0;
+
+ if( desired->alphaBits > 0 )
+ {
+ extraDiff += ( desired->alphaBits - current->alphaBits ) *
+ ( desired->alphaBits - current->alphaBits );
+ }
+
+ if( desired->depthBits > 0 )
+ {
+ extraDiff += ( desired->depthBits - current->depthBits ) *
+ ( desired->depthBits - current->depthBits );
+ }
+
+ if( desired->stencilBits > 0 )
+ {
+ extraDiff += ( desired->stencilBits - current->stencilBits ) *
+ ( desired->stencilBits - current->stencilBits );
+ }
+
+ if( desired->accumRedBits > 0 )
+ {
+ extraDiff += ( desired->accumRedBits - current->accumRedBits ) *
+ ( desired->accumRedBits - current->accumRedBits );
+ }
+
+ if( desired->accumGreenBits > 0 )
+ {
+ extraDiff += ( desired->accumGreenBits - current->accumGreenBits ) *
+ ( desired->accumGreenBits - current->accumGreenBits );
+ }
+
+ if( desired->accumBlueBits > 0 )
+ {
+ extraDiff += ( desired->accumBlueBits - current->accumBlueBits ) *
+ ( desired->accumBlueBits - current->accumBlueBits );
+ }
+
+ if( desired->accumAlphaBits > 0 )
+ {
+ extraDiff += ( desired->accumAlphaBits - current->accumAlphaBits ) *
+ ( desired->accumAlphaBits - current->accumAlphaBits );
+ }
+
+ if( desired->samples > 0 )
+ {
+ extraDiff += ( desired->samples - current->samples ) *
+ ( desired->samples - current->samples );
+ }
+ }
+
+ // Figure out if the current one is better than the best one found so far
+
+ if( missing < leastMissing )
+ {
+ closest = current;
+ }
+ else if( missing == leastMissing )
+ {
+ if( desiresColor )
+ {
+ if( ( colorDiff < leastColorDiff ) ||
+ ( colorDiff == leastColorDiff && extraDiff < leastExtraDiff ) )
+ {
+ closest = current;
+ }
+ }
+ else
+ {
+ if( ( extraDiff < leastExtraDiff ) ||
+ ( extraDiff == leastExtraDiff && colorDiff < leastColorDiff ) )
+ {
+ closest = current;
+ }
+ }
+ }
+
+ if( current == closest )
+ {
+ leastMissing = missing;
+ leastColorDiff = colorDiff;
+ leastExtraDiff = extraDiff;
+ }
+ }
+
+ return closest;
+}
+
+
+//************************************************************************
+//**** GLFW user functions ****
+//************************************************************************
+
+//========================================================================
+// Create the GLFW window and its associated context
+//========================================================================
+
+GLFWAPI int glfwOpenWindow( int width, int height,
+ int redbits, int greenbits, int bluebits, int alphabits,
+ int depthbits, int stencilbits, int mode )
+{
+ _GLFWfbconfig fbconfig;
+ _GLFWwndconfig wndconfig;
+
+ // Is GLFW initialized?
+ if( !_glfwInitialized || _glfwWin.opened )
+ {
+ return GL_FALSE;
+ }
+
+ // Set up desired framebuffer config
+ fbconfig.redBits = Max( redbits, 0 );
+ fbconfig.greenBits = Max( greenbits, 0 );
+ fbconfig.blueBits = Max( bluebits, 0 );
+ fbconfig.alphaBits = Max( alphabits, 0 );
+ fbconfig.depthBits = Max( depthbits, 0 );
+ fbconfig.stencilBits = Max( stencilbits, 0 );
+ fbconfig.accumRedBits = Max( _glfwLibrary.hints.accumRedBits, 0 );
+ fbconfig.accumGreenBits = Max( _glfwLibrary.hints.accumGreenBits, 0 );
+ fbconfig.accumBlueBits = Max( _glfwLibrary.hints.accumBlueBits, 0 );
+ fbconfig.accumAlphaBits = Max( _glfwLibrary.hints.accumAlphaBits, 0 );
+ fbconfig.auxBuffers = Max( _glfwLibrary.hints.auxBuffers, 0 );
+ fbconfig.stereo = _glfwLibrary.hints.stereo ? GL_TRUE : GL_FALSE;
+ fbconfig.samples = Max( _glfwLibrary.hints.samples, 0 );
+
+ // Set up desired window config
+ wndconfig.mode = mode;
+ wndconfig.refreshRate = Max( _glfwLibrary.hints.refreshRate, 0 );
+ wndconfig.windowNoResize = _glfwLibrary.hints.windowNoResize ? GL_TRUE : GL_FALSE;
+ wndconfig.glMajor = Max( _glfwLibrary.hints.glMajor, 1 );
+ wndconfig.glMinor = Max( _glfwLibrary.hints.glMinor, 0 );
+ wndconfig.glForward = _glfwLibrary.hints.glForward ? GL_TRUE : GL_FALSE;
+ wndconfig.glDebug = _glfwLibrary.hints.glDebug ? GL_TRUE : GL_FALSE;
+ wndconfig.glProfile = _glfwLibrary.hints.glProfile;
+
+ if( wndconfig.glMajor == 1 && wndconfig.glMinor > 5 )
+ {
+ // OpenGL 1.x series ended with version 1.5
+ return GL_FALSE;
+ }
+ else if( wndconfig.glMajor == 2 && wndconfig.glMinor > 1 )
+ {
+ // OpenGL 2.x series ended with version 2.1
+ return GL_FALSE;
+ }
+ else if( wndconfig.glMajor == 3 && wndconfig.glMinor > 3 )
+ {
+ // OpenGL 3.x series ended with version 3.3
+ return GL_FALSE;
+ }
+ else
+ {
+ // For now, let everything else through
+ }
+
+ if( wndconfig.glProfile &&
+ ( wndconfig.glMajor < 3 || ( wndconfig.glMajor == 3 && wndconfig.glMinor < 2 ) ) )
+ {
+ // Context profiles are only defined for OpenGL version 3.2 and above
+ return GL_FALSE;
+ }
+
+ if( wndconfig.glForward && wndconfig.glMajor < 3 )
+ {
+ // Forward-compatible contexts are only defined for OpenGL version 3.0 and above
+ return GL_FALSE;
+ }
+
+ // Clear for next open call
+ _glfwClearWindowHints();
+
+ // Check input arguments
+ if( mode != GLFW_WINDOW && mode != GLFW_FULLSCREEN )
+ {
+ return GL_FALSE;
+ }
+
+ // Clear GLFW window state
+ _glfwWin.active = GL_TRUE;
+ _glfwWin.iconified = GL_FALSE;
+ _glfwWin.mouseLock = GL_FALSE;
+ _glfwWin.autoPollEvents = GL_TRUE;
+ _glfwClearInput();
+
+ // Unregister all callback functions
+ _glfwWin.windowSizeCallback = NULL;
+ _glfwWin.windowCloseCallback = NULL;
+ _glfwWin.windowRefreshCallback = NULL;
+ _glfwWin.keyCallback = NULL;
+ _glfwWin.charCallback = NULL;
+ _glfwWin.mousePosCallback = NULL;
+ _glfwWin.mouseButtonCallback = NULL;
+ _glfwWin.mouseWheelCallback = NULL;
+
+ // Check width & height
+ if( width > 0 && height <= 0 )
+ {
+ // Set the window aspect ratio to 4:3
+ height = (width * 3) / 4;
+ }
+ else if( width <= 0 && height > 0 )
+ {
+ // Set the window aspect ratio to 4:3
+ width = (height * 4) / 3;
+ }
+ else if( width <= 0 && height <= 0 )
+ {
+ // Default window size
+ width = 640;
+ height = 480;
+ }
+
+ // Remember window settings
+ _glfwWin.width = width;
+ _glfwWin.height = height;
+ _glfwWin.fullscreen = (mode == GLFW_FULLSCREEN ? GL_TRUE : GL_FALSE);
+
+ // Platform specific window opening routine
+ if( !_glfwPlatformOpenWindow( width, height, &wndconfig, &fbconfig ) )
+ {
+ return GL_FALSE;
+ }
+
+ // Flag that window is now opened
+ _glfwWin.opened = GL_TRUE;
+
+ // Get window parameters (such as color buffer bits etc)
+ _glfwPlatformRefreshWindowParams();
+
+ // Get OpenGL version
+ _glfwParseGLVersion( &_glfwWin.glMajor, &_glfwWin.glMinor,
+ &_glfwWin.glRevision );
+
+ if( _glfwWin.glMajor < wndconfig.glMajor ||
+ ( _glfwWin.glMajor == wndconfig.glMajor &&
+ _glfwWin.glMinor < wndconfig.glMinor ) )
+ {
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ // Do we have non-power-of-two textures (added to core in version 2.0)?
+ _glfwWin.has_GL_ARB_texture_non_power_of_two =
+ ( _glfwWin.glMajor >= 2 ) ||
+ glfwExtensionSupported( "GL_ARB_texture_non_power_of_two" );
+
+ // Do we have automatic mipmap generation (added to core in version 1.4)?
+ _glfwWin.has_GL_SGIS_generate_mipmap =
+ ( _glfwWin.glMajor >= 2 ) || ( _glfwWin.glMinor >= 4 ) ||
+ glfwExtensionSupported( "GL_SGIS_generate_mipmap" );
+
+ if( _glfwWin.glMajor > 2 )
+ {
+ _glfwWin.GetStringi = (PFNGLGETSTRINGIPROC) glfwGetProcAddress( "glGetStringi" );
+ if( !_glfwWin.GetStringi )
+ {
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+ }
+
+ // If full-screen mode was requested, disable mouse cursor
+ if( mode == GLFW_FULLSCREEN )
+ {
+ glfwDisable( GLFW_MOUSE_CURSOR );
+ }
+
+ // Start by clearing the front buffer to black (avoid ugly desktop
+ // remains in our OpenGL window)
+ glClear( GL_COLOR_BUFFER_BIT );
+ _glfwPlatformSwapBuffers();
+
+ return GL_TRUE;
+}
+
+
+//========================================================================
+// Set hints for opening the window
+//========================================================================
+
+GLFWAPI void glfwOpenWindowHint( int target, int hint )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized )
+ {
+ return;
+ }
+
+ switch( target )
+ {
+ case GLFW_REFRESH_RATE:
+ _glfwLibrary.hints.refreshRate = hint;
+ break;
+ case GLFW_ACCUM_RED_BITS:
+ _glfwLibrary.hints.accumRedBits = hint;
+ break;
+ case GLFW_ACCUM_GREEN_BITS:
+ _glfwLibrary.hints.accumGreenBits = hint;
+ break;
+ case GLFW_ACCUM_BLUE_BITS:
+ _glfwLibrary.hints.accumBlueBits = hint;
+ break;
+ case GLFW_ACCUM_ALPHA_BITS:
+ _glfwLibrary.hints.accumAlphaBits = hint;
+ break;
+ case GLFW_AUX_BUFFERS:
+ _glfwLibrary.hints.auxBuffers = hint;
+ break;
+ case GLFW_STEREO:
+ _glfwLibrary.hints.stereo = hint;
+ break;
+ case GLFW_WINDOW_NO_RESIZE:
+ _glfwLibrary.hints.windowNoResize = hint;
+ break;
+ case GLFW_FSAA_SAMPLES:
+ _glfwLibrary.hints.samples = hint;
+ break;
+ case GLFW_OPENGL_VERSION_MAJOR:
+ _glfwLibrary.hints.glMajor = hint;
+ break;
+ case GLFW_OPENGL_VERSION_MINOR:
+ _glfwLibrary.hints.glMinor = hint;
+ break;
+ case GLFW_OPENGL_FORWARD_COMPAT:
+ _glfwLibrary.hints.glForward = hint;
+ break;
+ case GLFW_OPENGL_DEBUG_CONTEXT:
+ _glfwLibrary.hints.glDebug = hint;
+ break;
+ case GLFW_OPENGL_PROFILE:
+ _glfwLibrary.hints.glProfile = hint;
+ break;
+ default:
+ break;
+ }
+}
+
+
+//========================================================================
+// Properly kill the window / video display
+//========================================================================
+
+GLFWAPI void glfwCloseWindow( void )
+{
+ if( !_glfwInitialized )
+ {
+ return;
+ }
+
+ // Show mouse pointer again (if hidden)
+ glfwEnable( GLFW_MOUSE_CURSOR );
+
+ _glfwPlatformCloseWindow();
+
+ memset( &_glfwWin, 0, sizeof(_glfwWin) );
+ _glfwWin.opened = GL_FALSE;
+}
+
+
+//========================================================================
+// glfwSetWindowTitle() - Set the window title
+//========================================================================
+
+GLFWAPI void glfwSetWindowTitle( const char *title )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Set window title
+ _glfwPlatformSetWindowTitle( title );
+}
+
+
+//========================================================================
+// glfwGetWindowSize() - Get the window size
+//========================================================================
+
+GLFWAPI void glfwGetWindowSize( int *width, int *height )
+{
+ if( width != NULL )
+ {
+ *width = _glfwWin.width;
+ }
+ if( height != NULL )
+ {
+ *height = _glfwWin.height;
+ }
+}
+
+
+//========================================================================
+// glfwSetWindowSize() - Set the window size
+//========================================================================
+
+GLFWAPI void glfwSetWindowSize( int width, int height )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened || _glfwWin.iconified )
+ {
+ return;
+ }
+
+ // Don't do anything if the window size did not change
+ if( width == _glfwWin.width && height == _glfwWin.height )
+ {
+ return;
+ }
+
+ // Change window size
+ _glfwPlatformSetWindowSize( width, height );
+
+ // Refresh window parameters (may have changed due to changed video
+ // modes)
+ _glfwPlatformRefreshWindowParams();
+}
+
+
+//========================================================================
+// glfwSetWindowPos() - Set the window position
+//========================================================================
+
+GLFWAPI void glfwSetWindowPos( int x, int y )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened || _glfwWin.fullscreen ||
+ _glfwWin.iconified )
+ {
+ return;
+ }
+
+ // Set window position
+ _glfwPlatformSetWindowPos( x, y );
+}
+
+
+//========================================================================
+// glfwIconfyWindow() - Window iconification
+//========================================================================
+
+GLFWAPI void glfwIconifyWindow( void )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened || _glfwWin.iconified )
+ {
+ return;
+ }
+
+ // Iconify window
+ _glfwPlatformIconifyWindow();
+}
+
+
+//========================================================================
+// glfwRestoreWindow() - Window un-iconification
+//========================================================================
+
+GLFWAPI void glfwRestoreWindow( void )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened || !_glfwWin.iconified )
+ {
+ return;
+ }
+
+ // Restore iconified window
+ _glfwPlatformRestoreWindow();
+
+ // Refresh window parameters
+ _glfwPlatformRefreshWindowParams();
+}
+
+
+//========================================================================
+// Swap buffers (double-buffering) and poll any new events
+//========================================================================
+
+GLFWAPI void glfwSwapBuffers( void )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Update display-buffer
+ if( _glfwWin.opened )
+ {
+ _glfwPlatformSwapBuffers();
+ }
+
+ // Check for window messages
+ if( _glfwWin.autoPollEvents )
+ {
+ glfwPollEvents();
+ }
+}
+
+
+//========================================================================
+// glfwSwapInterval() - Set double buffering swap interval (0 = vsync off)
+//========================================================================
+
+GLFWAPI void glfwSwapInterval( int interval )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Set double buffering swap interval
+ _glfwPlatformSwapInterval( interval );
+}
+
+
+//========================================================================
+// glfwGetWindowParam() - Get window parameter
+//========================================================================
+
+GLFWAPI int glfwGetWindowParam( int param )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized )
+ {
+ return 0;
+ }
+
+ // Is the window opened?
+ if( !_glfwWin.opened )
+ {
+ if( param == GLFW_OPENED )
+ {
+ return GL_FALSE;
+ }
+ return 0;
+ }
+
+ // Window parameters
+ switch( param )
+ {
+ case GLFW_OPENED:
+ return GL_TRUE;
+ case GLFW_ACTIVE:
+ return _glfwWin.active;
+ case GLFW_ICONIFIED:
+ return _glfwWin.iconified;
+ case GLFW_ACCELERATED:
+ return _glfwWin.accelerated;
+ case GLFW_RED_BITS:
+ return _glfwWin.redBits;
+ case GLFW_GREEN_BITS:
+ return _glfwWin.greenBits;
+ case GLFW_BLUE_BITS:
+ return _glfwWin.blueBits;
+ case GLFW_ALPHA_BITS:
+ return _glfwWin.alphaBits;
+ case GLFW_DEPTH_BITS:
+ return _glfwWin.depthBits;
+ case GLFW_STENCIL_BITS:
+ return _glfwWin.stencilBits;
+ case GLFW_ACCUM_RED_BITS:
+ return _glfwWin.accumRedBits;
+ case GLFW_ACCUM_GREEN_BITS:
+ return _glfwWin.accumGreenBits;
+ case GLFW_ACCUM_BLUE_BITS:
+ return _glfwWin.accumBlueBits;
+ case GLFW_ACCUM_ALPHA_BITS:
+ return _glfwWin.accumAlphaBits;
+ case GLFW_AUX_BUFFERS:
+ return _glfwWin.auxBuffers;
+ case GLFW_STEREO:
+ return _glfwWin.stereo;
+ case GLFW_REFRESH_RATE:
+ return _glfwWin.refreshRate;
+ case GLFW_WINDOW_NO_RESIZE:
+ return _glfwWin.windowNoResize;
+ case GLFW_FSAA_SAMPLES:
+ return _glfwWin.samples;
+ case GLFW_OPENGL_VERSION_MAJOR:
+ return _glfwWin.glMajor;
+ case GLFW_OPENGL_VERSION_MINOR:
+ return _glfwWin.glMinor;
+ case GLFW_OPENGL_FORWARD_COMPAT:
+ return _glfwWin.glForward;
+ case GLFW_OPENGL_DEBUG_CONTEXT:
+ return _glfwWin.glDebug;
+ case GLFW_OPENGL_PROFILE:
+ return _glfwWin.glProfile;
+ default:
+ return 0;
+ }
+}
+
+
+//========================================================================
+// glfwSetWindowSizeCallback() - Set callback function for window size
+// changes
+//========================================================================
+
+GLFWAPI void glfwSetWindowSizeCallback( GLFWwindowsizefun cbfun )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Set callback function
+ _glfwWin.windowSizeCallback = cbfun;
+
+ // Call the callback function to let the application know the current
+ // window size
+ if( cbfun )
+ {
+ cbfun( _glfwWin.width, _glfwWin.height );
+ }
+}
+
+//========================================================================
+// glfwSetWindowCloseCallback() - Set callback function for window close
+// events
+//========================================================================
+
+GLFWAPI void glfwSetWindowCloseCallback( GLFWwindowclosefun cbfun )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Set callback function
+ _glfwWin.windowCloseCallback = cbfun;
+}
+
+
+//========================================================================
+// glfwSetWindowRefreshCallback() - Set callback function for window
+// refresh events
+//========================================================================
+
+GLFWAPI void glfwSetWindowRefreshCallback( GLFWwindowrefreshfun cbfun )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Set callback function
+ _glfwWin.windowRefreshCallback = cbfun;
+}
+
+
+//========================================================================
+// glfwPollEvents() - Poll for new window and input events
+//========================================================================
+
+GLFWAPI void glfwPollEvents( void )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Poll for new events
+ _glfwPlatformPollEvents();
+}
+
+
+//========================================================================
+// glfwWaitEvents() - Wait for new window and input events
+//========================================================================
+
+GLFWAPI void glfwWaitEvents( void )
+{
+ // Is GLFW initialized?
+ if( !_glfwInitialized || !_glfwWin.opened )
+ {
+ return;
+ }
+
+ // Poll for new events
+ _glfwPlatformWaitEvents();
+}
+
diff --git a/lib/x11/CMakeLists.txt b/lib/x11/CMakeLists.txt
new file mode 100644
index 00000000..fde2d773
--- /dev/null
+++ b/lib/x11/CMakeLists.txt
@@ -0,0 +1,36 @@
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/x11_config.h.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/x11_config.h @ONLY)
+
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/libglfw.pc.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/libglfw.pc @ONLY)
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+ ${GLFW_INCLUDE_DIR})
+
+set(libglfw_SOURCES
+ ${common_SOURCES}
+ x11_enable.c
+ x11_fullscreen.c
+ x11_glext.c
+ x11_init.c
+ x11_joystick.c
+ x11_keysym2unicode.c
+ x11_time.c
+ x11_window.c)
+
+add_library(libglfwStatic STATIC ${libglfw_SOURCES})
+add_library(libglfwShared SHARED ${libglfw_SOURCES})
+target_link_libraries(libglfwShared ${GLFW_LIBRARIES})
+set_target_properties(libglfwStatic libglfwShared PROPERTIES
+ CLEAN_DIRECT_OUTPUT 1
+ OUTPUT_NAME glfw
+)
+
+install(TARGETS libglfwStatic libglfwShared DESTINATION lib)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libglfw.pc DESTINATION lib/pkgconfig)
+
diff --git a/lib/x11/libglfw.pc.cmake b/lib/x11/libglfw.pc.cmake
new file mode 100644
index 00000000..adc455f8
--- /dev/null
+++ b/lib/x11/libglfw.pc.cmake
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: GLFW
+Description: A portable framework for OpenGL development
+Version: 2.7
+URL: http://glfw.sourceforge.net/
+Libs: -L${libdir} -lglfw @GLFW_LIBRARIES@
+Cflags: -I${includedir}
diff --git a/lib/x11/platform.h b/lib/x11/platform.h
new file mode 100644
index 00000000..831f16f1
--- /dev/null
+++ b/lib/x11/platform.h
@@ -0,0 +1,433 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: X11/GLX
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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 _platform_h_
+#define _platform_h_
+
+
+// This is the X11 version of GLFW
+#define _GLFW_X11
+
+
+// Include files
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "../../include/GL/glfw.h"
+#include "x11_config.h"
+
+// We need declarations for GLX version 1.3 or above even if the server doesn't
+// support version 1.3
+#ifndef GLX_VERSION_1_3
+ #error "GLX header version 1.3 or above is required"
+#endif
+
+#if defined( _GLFW_HAS_XF86VIDMODE ) && defined( _GLFW_HAS_XRANDR )
+ #error "Xf86VidMode and RandR extensions cannot both be enabled"
+#endif
+
+// With XFree86, we can use the XF86VidMode extension
+#if defined( _GLFW_HAS_XF86VIDMODE )
+ #include
+#endif
+
+#if defined( _GLFW_HAS_XRANDR )
+ #include
+#endif
+
+// Do we have support for dlopen/dlsym?
+#if defined( _GLFW_HAS_DLOPEN )
+ #include
+#endif
+
+// We support two different ways for getting the number of processors in
+// the system: sysconf (POSIX) and sysctl (BSD?)
+#if defined( _GLFW_HAS_SYSCONF )
+
+ // Use a single constant for querying number of online processors using
+ // the sysconf function (e.g. SGI defines _SC_NPROC_ONLN instead of
+ // _SC_NPROCESSORS_ONLN)
+ #ifndef _SC_NPROCESSORS_ONLN
+ #ifdef _SC_NPROC_ONLN
+ #define _SC_NPROCESSORS_ONLN _SC_NPROC_ONLN
+ #else
+ #error POSIX constant _SC_NPROCESSORS_ONLN not defined!
+ #endif
+ #endif
+
+ // Macro for querying the number of processors
+ #define _glfw_numprocessors(n) n=(int)sysconf(_SC_NPROCESSORS_ONLN)
+
+#elif defined( _GLFW_HAS_SYSCTL )
+
+ #include
+ #include
+
+ // Macro for querying the number of processors
+ #define _glfw_numprocessors(n) { \
+ int mib[2], ncpu; \
+ size_t len = 1; \
+ mib[0] = CTL_HW; \
+ mib[1] = HW_NCPU; \
+ n = 1; \
+ if( sysctl( mib, 2, &ncpu, &len, NULL, 0 ) != -1 ) \
+ { \
+ if( len > 0 ) \
+ { \
+ n = ncpu; \
+ } \
+ } \
+ }
+
+#else
+
+ // If neither sysconf nor sysctl is supported, assume single processor
+ // system
+ #define _glfw_numprocessors(n) n=1
+
+#endif
+
+// Pointer length integer
+// One day, this will most likely move into glfw.h
+typedef intptr_t GLFWintptr;
+
+
+#ifndef GLX_SGI_swap_control
+
+// Function signature for GLX_SGI_swap_control
+typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval);
+
+#endif /*GLX_SGI_swap_control*/
+
+
+#ifndef GLX_SGIX_fbconfig
+
+/* Type definitions for GLX_SGIX_fbconfig */
+typedef XID GLXFBConfigIDSGIX;
+typedef struct __GLXFBConfigRec *GLXFBConfigSGIX;
+
+/* Function signatures for GLX_SGIX_fbconfig */
+typedef int ( * PFNGLXGETFBCONFIGATTRIBSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int attribute, int *value);
+typedef GLXFBConfigSGIX * ( * PFNGLXCHOOSEFBCONFIGSGIXPROC) (Display *dpy, int screen, int *attrib_list, int *nelements);
+typedef GLXContext ( * PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct);
+typedef XVisualInfo * ( * PFNGLXGETVISUALFROMFBCONFIGSGIXPROC) (Display *dpy, GLXFBConfigSGIX config);
+
+/* Tokens for GLX_SGIX_fbconfig */
+#define GLX_WINDOW_BIT_SGIX 0x00000001
+#define GLX_PIXMAP_BIT_SGIX 0x00000002
+#define GLX_RGBA_BIT_SGIX 0x00000001
+#define GLX_COLOR_INDEX_BIT_SGIX 0x00000002
+#define GLX_DRAWABLE_TYPE_SGIX 0x8010
+#define GLX_RENDER_TYPE_SGIX 0x8011
+#define GLX_X_RENDERABLE_SGIX 0x8012
+#define GLX_FBCONFIG_ID_SGIX 0x8013
+#define GLX_RGBA_TYPE_SGIX 0x8014
+#define GLX_COLOR_INDEX_TYPE_SGIX 0x8015
+#define GLX_SCREEN_EXT 0x800C
+
+#endif /*GLX_SGIX_fbconfig*/
+
+
+#ifndef GLX_ARB_create_context
+
+/* Tokens for glXCreateContextAttribsARB attributes */
+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define GLX_CONTEXT_FLAGS_ARB 0x2094
+
+/* Bits for WGL_CONTEXT_FLAGS_ARB */
+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x0001
+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+
+/* Prototype for glXCreateContextAttribs */
+typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)( Display *display, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
+
+#endif /*GLX_ARB_create_context*/
+
+
+#ifndef GLX_ARB_create_context_profile
+
+/* Tokens for glXCreateContextAttribsARB attributes */
+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
+
+/* BIts for GLX_CONTEXT_PROFILE_MASK_ARB */
+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+
+#endif /*GLX_ARB_create_context_profile*/
+
+
+#ifndef GL_VERSION_3_0
+
+typedef const GLubyte * (APIENTRY *PFNGLGETSTRINGIPROC) (GLenum, GLuint);
+
+#endif /*GL_VERSION_3_0*/
+
+
+
+//========================================================================
+// Global variables (GLFW internals)
+//========================================================================
+
+//------------------------------------------------------------------------
+// Window structure
+//------------------------------------------------------------------------
+typedef struct _GLFWwin_struct _GLFWwin;
+
+struct _GLFWwin_struct {
+
+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
+
+ // User callback functions
+ GLFWwindowsizefun windowSizeCallback;
+ GLFWwindowclosefun windowCloseCallback;
+ GLFWwindowrefreshfun windowRefreshCallback;
+ GLFWmousebuttonfun mouseButtonCallback;
+ GLFWmouseposfun mousePosCallback;
+ GLFWmousewheelfun mouseWheelCallback;
+ GLFWkeyfun keyCallback;
+ GLFWcharfun charCallback;
+
+ // User selected window settings
+ int fullscreen; // Fullscreen flag
+ int mouseLock; // Mouse-lock flag
+ int autoPollEvents; // Auto polling flag
+ int sysKeysDisabled; // System keys disabled flag
+ int windowNoResize; // Resize- and maximize gadgets disabled flag
+ int refreshRate; // Vertical monitor refresh rate
+
+ // Window status & parameters
+ int opened; // Flag telling if window is opened or not
+ int active; // Application active flag
+ int iconified; // Window iconified flag
+ int width, height; // Window width and heigth
+ int accelerated; // GL_TRUE if window is HW accelerated
+
+ // Framebuffer attributes
+ int redBits;
+ int greenBits;
+ int blueBits;
+ int alphaBits;
+ int depthBits;
+ int stencilBits;
+ int accumRedBits;
+ int accumGreenBits;
+ int accumBlueBits;
+ int accumAlphaBits;
+ int auxBuffers;
+ int stereo;
+ int samples;
+
+ // OpenGL extensions and context attributes
+ int has_GL_SGIS_generate_mipmap;
+ int has_GL_ARB_texture_non_power_of_two;
+ int glMajor, glMinor, glRevision;
+ int glForward, glDebug, glProfile;
+
+ PFNGLGETSTRINGIPROC GetStringi;
+
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+ // Platform specific window resources
+ Colormap colormap; // Window colormap
+ Window window; // Window
+ Window root; // Root window for screen
+ int screen; // Screen ID
+ XVisualInfo *visual; // Visual for selected GLXFBConfig
+ GLXFBConfigID fbconfigID; // ID of selected GLXFBConfig
+ GLXContext context; // OpenGL rendering context
+ Atom wmDeleteWindow; // WM_DELETE_WINDOW atom
+ Atom wmPing; // _NET_WM_PING atom
+ Atom wmState; // _NET_WM_STATE atom
+ Atom wmStateFullscreen; // _NET_WM_STATE_FULLSCREEN atom
+ Atom wmActiveWindow; // _NET_ACTIVE_WINDOW atom
+ Cursor cursor; // Invisible cursor for hidden cursor
+
+ // GLX extensions
+ PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI;
+ PFNGLXGETFBCONFIGATTRIBSGIXPROC GetFBConfigAttribSGIX;
+ PFNGLXCHOOSEFBCONFIGSGIXPROC ChooseFBConfigSGIX;
+ PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC CreateContextWithConfigSGIX;
+ PFNGLXGETVISUALFROMFBCONFIGSGIXPROC GetVisualFromFBConfigSGIX;
+ PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
+ GLboolean has_GLX_SGIX_fbconfig;
+ GLboolean has_GLX_SGI_swap_control;
+ GLboolean has_GLX_ARB_multisample;
+ GLboolean has_GLX_ARB_create_context;
+ GLboolean has_GLX_ARB_create_context_profile;
+
+ // Various platform specific internal variables
+ GLboolean hasEWMH; // True if window manager supports EWMH
+ GLboolean overrideRedirect; // True if window is OverrideRedirect
+ GLboolean keyboardGrabbed; // True if keyboard is currently grabbed
+ GLboolean pointerGrabbed; // True if pointer is currently grabbed
+ GLboolean pointerHidden; // True if pointer is currently hidden
+
+ // Screensaver data
+ struct {
+ int changed;
+ int timeout;
+ int interval;
+ int blanking;
+ int exposure;
+ } Saver;
+
+ // Fullscreen data
+ struct {
+ int modeChanged;
+#if defined( _GLFW_HAS_XF86VIDMODE )
+ XF86VidModeModeInfo oldMode;
+#endif
+#if defined( _GLFW_HAS_XRANDR )
+ SizeID oldSizeID;
+ int oldWidth;
+ int oldHeight;
+ Rotation oldRotation;
+#endif
+ } FS;
+};
+
+GLFWGLOBAL _GLFWwin _glfwWin;
+
+
+//------------------------------------------------------------------------
+// User input status (most of this should go in _GLFWwin)
+//------------------------------------------------------------------------
+GLFWGLOBAL struct {
+
+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
+
+ // Mouse status
+ int MousePosX, MousePosY;
+ int WheelPos;
+ char MouseButton[ GLFW_MOUSE_BUTTON_LAST+1 ];
+
+ // Keyboard status
+ char Key[ GLFW_KEY_LAST+1 ];
+ int LastChar;
+
+ // User selected settings
+ int StickyKeys;
+ int StickyMouseButtons;
+ int KeyRepeat;
+
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+ // Platform specific internal variables
+ int MouseMoved, CursorPosX, CursorPosY;
+
+} _glfwInput;
+
+
+//------------------------------------------------------------------------
+// Library global data
+//------------------------------------------------------------------------
+GLFWGLOBAL struct {
+
+// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
+
+ // Window opening hints
+ _GLFWhints hints;
+
+// ========= PLATFORM SPECIFIC PART ======================================
+
+ Display *display;
+
+ // Server-side GLX version
+ int glxMajor, glxMinor;
+
+ struct {
+ int available;
+ int eventBase;
+ int errorBase;
+ } XF86VidMode;
+
+ struct {
+ int available;
+ int eventBase;
+ int errorBase;
+ } XRandR;
+
+ // Timer data
+ struct {
+ double resolution;
+ long long t0;
+ } Timer;
+
+#if defined(_GLFW_DLOPEN_LIBGL)
+ struct {
+ void *libGL; // dlopen handle for libGL.so
+ } Libs;
+#endif
+} _glfwLibrary;
+
+
+//------------------------------------------------------------------------
+// Joystick information & state
+//------------------------------------------------------------------------
+GLFWGLOBAL struct {
+ int Present;
+ int fd;
+ int NumAxes;
+ int NumButtons;
+ float *Axis;
+ unsigned char *Button;
+} _glfwJoy[ GLFW_JOYSTICK_LAST + 1 ];
+
+
+//========================================================================
+// Prototypes for platform specific internal functions
+//========================================================================
+
+// Time
+void _glfwInitTimer( void );
+
+// Fullscreen support
+int _glfwGetClosestVideoMode( int screen, int *width, int *height, int *rate );
+void _glfwSetVideoModeMODE( int screen, int mode, int rate );
+void _glfwSetVideoMode( int screen, int *width, int *height, int *rate );
+void _glfwRestoreVideoMode( void );
+
+// Joystick input
+void _glfwInitJoysticks( void );
+void _glfwTerminateJoysticks( void );
+
+// Unicode support
+long _glfwKeySym2Unicode( KeySym keysym );
+
+
+#endif // _platform_h_
diff --git a/lib/x11/x11_config.h.cmake b/lib/x11/x11_config.h.cmake
new file mode 100644
index 00000000..d578d574
--- /dev/null
+++ b/lib/x11/x11_config.h.cmake
@@ -0,0 +1,14 @@
+/* Configure build time options of GLFW */
+
+/* Define this to 1 if XRandR is available */
+#cmakedefine _GLFW_HAS_XRANDR 1
+/* Define this to 1 if Xf86VidMode is available */
+#cmakedefine _GLFW_HAS_XF86VIDMODE 1
+
+/* Define this to 1 if glXGetProcAddress is available */
+#cmakedefine _GLFW_HAS_GLXGETPROCADDRESS 1
+/* Define this to 1 if glXGetProcAddressARB is available */
+#cmakedefine _GLFW_HAS_GLXGETPROCADDRESSARB 1
+/* Define this to 1 if glXGetProcAddressEXT is available */
+#cmakedefine _GLFW_HAS_GLXGETPROCADDRESSEXT 1
+
diff --git a/lib/x11/x11_enable.c b/lib/x11/x11_enable.c
new file mode 100644
index 00000000..88308d5a
--- /dev/null
+++ b/lib/x11/x11_enable.c
@@ -0,0 +1,64 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: X11 (Unix)
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Enable system keys
+//========================================================================
+
+void _glfwPlatformEnableSystemKeys( void )
+{
+ if( _glfwWin.keyboardGrabbed )
+ {
+ XUngrabKeyboard( _glfwLibrary.display, CurrentTime );
+ _glfwWin.keyboardGrabbed = GL_FALSE;
+ }
+}
+
+//========================================================================
+// Disable system keys
+//========================================================================
+
+void _glfwPlatformDisableSystemKeys( void )
+{
+ if( XGrabKeyboard( _glfwLibrary.display, _glfwWin.window, True,
+ GrabModeAsync, GrabModeAsync, CurrentTime ) ==
+ GrabSuccess )
+ {
+ _glfwWin.keyboardGrabbed = GL_TRUE;
+ }
+}
+
diff --git a/lib/x11/x11_fullscreen.c b/lib/x11/x11_fullscreen.c
new file mode 100644
index 00000000..f720214b
--- /dev/null
+++ b/lib/x11/x11_fullscreen.c
@@ -0,0 +1,572 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: X11/GLX
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+//========================================================================
+// Convert BPP to RGB bits (based on "best guess")
+//========================================================================
+
+static void BPP2RGB( int bpp, int *r, int *g, int *b )
+{
+ int delta;
+
+ // Special case: BPP = 32 (I don't think this is necessary for X11??)
+ if( bpp == 32 )
+ bpp = 24;
+
+ // Convert "bits per pixel" to red, green & blue sizes
+ *r = *g = *b = bpp / 3;
+ delta = bpp - (*r * 3);
+ if( delta >= 1 )
+ {
+ *g = *g + 1;
+ }
+ if( delta == 2 )
+ {
+ *r = *r + 1;
+ }
+}
+
+
+//========================================================================
+// Finds the video mode closest in size to the specified desired size
+//========================================================================
+
+int _glfwGetClosestVideoMode( int screen, int *width, int *height, int *rate )
+{
+#if defined( _GLFW_HAS_XRANDR )
+ int i, match, bestmatch;
+ int sizecount, bestsize;
+ int ratecount, bestrate;
+ short *ratelist;
+ XRRScreenConfiguration *sc;
+ XRRScreenSize *sizelist;
+
+ if( _glfwLibrary.XRandR.available )
+ {
+ sc = XRRGetScreenInfo( _glfwLibrary.display,
+ RootWindow( _glfwLibrary.display, screen ) );
+
+ sizelist = XRRConfigSizes( sc, &sizecount );
+
+ // Find the best matching mode
+ bestsize = -1;
+ bestmatch = INT_MAX;
+ for( i = 0; i < sizecount; i++ )
+ {
+ match = (*width - sizelist[i].width) *
+ (*width - sizelist[i].width) +
+ (*height - sizelist[i].height) *
+ (*height - sizelist[i].height);
+ if( match < bestmatch )
+ {
+ bestmatch = match;
+ bestsize = i;
+ }
+ }
+
+ if( bestsize != -1 )
+ {
+ // Report width & height of best matching mode
+ *width = sizelist[bestsize].width;
+ *height = sizelist[bestsize].height;
+
+ if( *rate > 0 )
+ {
+ ratelist = XRRConfigRates( sc, bestsize, &ratecount );
+
+ bestrate = -1;
+ bestmatch = INT_MAX;
+ for( i = 0; i < ratecount; i++ )
+ {
+ match = abs( ratelist[i] - *rate );
+ if( match < bestmatch )
+ {
+ bestmatch = match;
+ bestrate = ratelist[i];
+ }
+ }
+
+ if( bestrate != -1 )
+ {
+ *rate = bestrate;
+ }
+ }
+ }
+
+ // Free modelist
+ XRRFreeScreenConfigInfo( sc );
+
+ if( bestsize != -1 )
+ {
+ return bestsize;
+ }
+ }
+#elif defined( _GLFW_HAS_XF86VIDMODE )
+ XF86VidModeModeInfo **modelist;
+ int modecount, i, bestmode, bestmatch, match;
+
+ // Use the XF86VidMode extension to control video resolution
+ if( _glfwLibrary.XF86VidMode.available )
+ {
+ // Get a list of all available display modes
+ XF86VidModeGetAllModeLines( _glfwLibrary.display, screen,
+ &modecount, &modelist );
+
+ // Find the best matching mode
+ bestmode = -1;
+ bestmatch = INT_MAX;
+ for( i = 0; i < modecount; i++ )
+ {
+ match = (*width - modelist[i]->hdisplay) *
+ (*width - modelist[i]->hdisplay) +
+ (*height - modelist[i]->vdisplay) *
+ (*height - modelist[i]->vdisplay);
+ if( match < bestmatch )
+ {
+ bestmatch = match;
+ bestmode = i;
+ }
+ }
+
+ if( bestmode != -1 )
+ {
+ // Report width & height of best matching mode
+ *width = modelist[ bestmode ]->hdisplay;
+ *height = modelist[ bestmode ]->vdisplay;
+ }
+
+ // Free modelist
+ XFree( modelist );
+
+ if( bestmode != -1 )
+ {
+ return bestmode;
+ }
+ }
+#endif
+
+ // Default: Simply use the screen resolution
+ *width = DisplayWidth( _glfwLibrary.display, screen );
+ *height = DisplayHeight( _glfwLibrary.display, screen );
+
+ return 0;
+}
+
+
+//========================================================================
+// Change the current video mode
+//========================================================================
+
+void _glfwSetVideoModeMODE( int screen, int mode, int rate )
+{
+#if defined( _GLFW_HAS_XRANDR )
+ XRRScreenConfiguration *sc;
+ Window root;
+
+ if( _glfwLibrary.XRandR.available )
+ {
+ root = RootWindow( _glfwLibrary.display, screen );
+ sc = XRRGetScreenInfo( _glfwLibrary.display, root );
+
+ // Remember old size and flag that we have changed the mode
+ if( !_glfwWin.FS.modeChanged )
+ {
+ _glfwWin.FS.oldSizeID = XRRConfigCurrentConfiguration( sc, &_glfwWin.FS.oldRotation );
+ _glfwWin.FS.oldWidth = DisplayWidth( _glfwLibrary.display, screen );
+ _glfwWin.FS.oldHeight = DisplayHeight( _glfwLibrary.display, screen );
+
+ _glfwWin.FS.modeChanged = GL_TRUE;
+ }
+
+ if( rate > 0 )
+ {
+ // Set desired configuration
+ XRRSetScreenConfigAndRate( _glfwLibrary.display,
+ sc,
+ root,
+ mode,
+ RR_Rotate_0,
+ (short) rate,
+ CurrentTime );
+ }
+ else
+ {
+ // Set desired configuration
+ XRRSetScreenConfig( _glfwLibrary.display,
+ sc,
+ root,
+ mode,
+ RR_Rotate_0,
+ CurrentTime );
+ }
+
+ XRRFreeScreenConfigInfo( sc );
+ }
+#elif defined( _GLFW_HAS_XF86VIDMODE )
+ XF86VidModeModeInfo **modelist;
+ int modecount;
+
+ // Use the XF86VidMode extension to control video resolution
+ if( _glfwLibrary.XF86VidMode.available )
+ {
+ // Get a list of all available display modes
+ XF86VidModeGetAllModeLines( _glfwLibrary.display, screen,
+ &modecount, &modelist );
+
+ // Unlock mode switch if necessary
+ if( _glfwWin.FS.modeChanged )
+ {
+ XF86VidModeLockModeSwitch( _glfwLibrary.display, screen, 0 );
+ }
+
+ // Change the video mode to the desired mode
+ XF86VidModeSwitchToMode( _glfwLibrary.display, screen,
+ modelist[ mode ] );
+
+ // Set viewport to upper left corner (where our window will be)
+ XF86VidModeSetViewPort( _glfwLibrary.display, screen, 0, 0 );
+
+ // Lock mode switch
+ XF86VidModeLockModeSwitch( _glfwLibrary.display, screen, 1 );
+
+ // Remember old mode and flag that we have changed the mode
+ if( !_glfwWin.FS.modeChanged )
+ {
+ _glfwWin.FS.oldMode = *modelist[ 0 ];
+ _glfwWin.FS.modeChanged = GL_TRUE;
+ }
+
+ // Free mode list
+ XFree( modelist );
+ }
+#endif
+}
+
+
+//========================================================================
+// Change the current video mode
+//========================================================================
+
+void _glfwSetVideoMode( int screen, int *width, int *height, int *rate )
+{
+ int bestmode;
+
+ // Find a best match mode
+ bestmode = _glfwGetClosestVideoMode( screen, width, height, rate );
+
+ // Change mode
+ _glfwSetVideoModeMODE( screen, bestmode, *rate );
+}
+
+
+//========================================================================
+// Restore the previously saved (original) video mode
+//========================================================================
+
+void _glfwRestoreVideoMode( void )
+{
+ if( _glfwWin.FS.modeChanged )
+ {
+#if defined( _GLFW_HAS_XRANDR )
+ if( _glfwLibrary.XRandR.available )
+ {
+ XRRScreenConfiguration *sc;
+
+ if( _glfwLibrary.XRandR.available )
+ {
+ sc = XRRGetScreenInfo( _glfwLibrary.display, _glfwWin.root );
+
+ XRRSetScreenConfig( _glfwLibrary.display,
+ sc,
+ _glfwWin.root,
+ _glfwWin.FS.oldSizeID,
+ _glfwWin.FS.oldRotation,
+ CurrentTime );
+
+ XRRFreeScreenConfigInfo( sc );
+ }
+ }
+#elif defined( _GLFW_HAS_XF86VIDMODE )
+ if( _glfwLibrary.XF86VidMode.available )
+ {
+ // Unlock mode switch
+ XF86VidModeLockModeSwitch( _glfwLibrary.display, _glfwWin.screen, 0 );
+
+ // Change the video mode back to the old mode
+ XF86VidModeSwitchToMode( _glfwLibrary.display,
+ _glfwWin.screen,
+ &_glfwWin.FS.oldMode );
+ }
+#endif
+ _glfwWin.FS.modeChanged = GL_FALSE;
+ }
+}
+
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+struct _glfwResolution
+{
+ int width;
+ int height;
+};
+
+//========================================================================
+// List available video modes
+//========================================================================
+
+int _glfwPlatformGetVideoModes( GLFWvidmode *list, int maxcount )
+{
+ int count, k, l, r, g, b, rgba, gl;
+ int depth, screen;
+ Display *dpy;
+ XVisualInfo *vislist, dummy;
+ int viscount, rgbcount, rescount;
+ int *rgbarray;
+ struct _glfwResolution *resarray;
+#if defined( _GLFW_HAS_XRANDR )
+ XRRScreenConfiguration *sc;
+ XRRScreenSize *sizelist;
+ int sizecount;
+#elif defined( _GLFW_HAS_XF86VIDMODE )
+ XF86VidModeModeInfo **modelist;
+ int modecount, width, height;
+#endif
+
+ // Get display and screen
+ dpy = _glfwLibrary.display;
+ screen = DefaultScreen( dpy );
+
+ // Get list of visuals
+ vislist = XGetVisualInfo( dpy, 0, &dummy, &viscount );
+ if( vislist == NULL )
+ {
+ return 0;
+ }
+
+ rgbarray = (int*) malloc( sizeof(int) * viscount );
+ rgbcount = 0;
+
+ // Build RGB array
+ for( k = 0; k < viscount; k++ )
+ {
+ // Does the visual support OpenGL & true color?
+ glXGetConfig( dpy, &vislist[k], GLX_USE_GL, &gl );
+ glXGetConfig( dpy, &vislist[k], GLX_RGBA, &rgba );
+ if( gl && rgba )
+ {
+ // Get color depth for this visual
+ depth = vislist[k].depth;
+
+ // Convert to RGB
+ BPP2RGB( depth, &r, &g, &b );
+ depth = (r<<16) | (g<<8) | b;
+
+ // Is this mode unique?
+ for( l = 0; l < rgbcount; l++ )
+ {
+ if( depth == rgbarray[ l ] )
+ {
+ break;
+ }
+ }
+ if( l >= rgbcount )
+ {
+ rgbarray[ rgbcount ] = depth;
+ rgbcount++;
+ }
+ }
+ }
+
+ rescount = 0;
+ resarray = NULL;
+
+ // Build resolution array
+#if defined( _GLFW_HAS_XRANDR )
+ if( _glfwLibrary.XRandR.available )
+ {
+ sc = XRRGetScreenInfo( dpy, RootWindow( dpy, screen ) );
+ sizelist = XRRConfigSizes( sc, &sizecount );
+
+ resarray = (struct _glfwResolution*) malloc( sizeof(struct _glfwResolution) * sizecount );
+
+ for( k = 0; k < sizecount; k++ )
+ {
+ resarray[ rescount ].width = sizelist[ k ].width;
+ resarray[ rescount ].height = sizelist[ k ].height;
+ rescount++;
+ }
+
+ XRRFreeScreenConfigInfo( sc );
+ }
+#elif defined( _GLFW_HAS_XF86VIDMODE )
+ if( _glfwLibrary.XF86VidMode.available )
+ {
+ XF86VidModeGetAllModeLines( dpy, screen, &modecount, &modelist );
+
+ resarray = (struct _glfwResolution*) malloc( sizeof(struct _glfwResolution) * modecount );
+
+ for( k = 0; k < modecount; k++ )
+ {
+ width = modelist[ k ]->hdisplay;
+ height = modelist[ k ]->vdisplay;
+
+ // Is this mode unique?
+ for( l = 0; l < rescount; l++ )
+ {
+ if( width == resarray[ l ].width && height == resarray[ l ].height )
+ {
+ break;
+ }
+ }
+
+ if( l >= rescount )
+ {
+ resarray[ rescount ].width = width;
+ resarray[ rescount ].height = height;
+ rescount++;
+ }
+ }
+
+ XFree( modelist );
+ }
+#endif
+
+ if( !resarray )
+ {
+ rescount = 1;
+ resarray = (struct _glfwResolution*) malloc( sizeof(struct _glfwResolution) * rescount );
+
+ resarray[ 0 ].width = DisplayWidth( dpy, screen );
+ resarray[ 0 ].height = DisplayHeight( dpy, screen );
+ }
+
+ // Build permutations of colors and resolutions
+ count = 0;
+ for( k = 0; k < rgbcount && count < maxcount; k++ )
+ {
+ for( l = 0; l < rescount && count < maxcount; l++ )
+ {
+ list[count].Width = resarray[ l ].width;
+ list[count].Height = resarray[ l ].height;
+ list[count].RedBits = (rgbarray[ k ] >> 16) & 255;
+ list[count].GreenBits = (rgbarray[ k ] >> 8) & 255;
+ list[count].BlueBits = rgbarray[ k ] & 255;
+ count++;
+ }
+ }
+
+ // Free visuals list
+ XFree( vislist );
+
+ free( resarray );
+ free( rgbarray );
+
+ return count;
+}
+
+
+//========================================================================
+// Get the desktop video mode
+//========================================================================
+
+void _glfwPlatformGetDesktopMode( GLFWvidmode *mode )
+{
+ Display *dpy;
+ int bpp, screen;
+#if defined( _GLFW_HAS_XF86VIDMODE )
+ XF86VidModeModeInfo **modelist;
+ int modecount;
+#endif
+
+ // Get display and screen
+ dpy = _glfwLibrary.display;
+ screen = DefaultScreen( dpy );
+
+ // Get display depth
+ bpp = DefaultDepth( dpy, screen );
+
+ // Convert BPP to RGB bits
+ BPP2RGB( bpp, &mode->RedBits, &mode->GreenBits, &mode->BlueBits );
+
+#if defined( _GLFW_HAS_XRANDR )
+ if( _glfwLibrary.XRandR.available )
+ {
+ if( _glfwWin.FS.modeChanged )
+ {
+ mode->Width = _glfwWin.FS.oldWidth;
+ mode->Height = _glfwWin.FS.oldHeight;
+ return;
+ }
+ }
+#elif defined( _GLFW_HAS_XF86VIDMODE )
+ if( _glfwLibrary.XF86VidMode.available )
+ {
+ if( _glfwWin.FS.modeChanged )
+ {
+ // The old (desktop) mode is stored in _glfwWin.FS.oldMode
+ mode->Width = _glfwWin.FS.oldMode.hdisplay;
+ mode->Height = _glfwWin.FS.oldMode.vdisplay;
+ }
+ else
+ {
+ // Use the XF86VidMode extension to get list of video modes
+ XF86VidModeGetAllModeLines( dpy, screen, &modecount,
+ &modelist );
+
+ // The first mode in the list is the current (desktio) mode
+ mode->Width = modelist[ 0 ]->hdisplay;
+ mode->Height = modelist[ 0 ]->vdisplay;
+
+ // Free list
+ XFree( modelist );
+ }
+
+ return;
+ }
+#endif
+
+ // Get current display width and height
+ mode->Width = DisplayWidth( dpy, screen );
+ mode->Height = DisplayHeight( dpy, screen );
+}
+
diff --git a/lib/x11/x11_glext.c b/lib/x11/x11_glext.c
new file mode 100644
index 00000000..bf77dcfa
--- /dev/null
+++ b/lib/x11/x11_glext.c
@@ -0,0 +1,90 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: X11/GLX
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+void (*glXGetProcAddress(const GLubyte *procName))();
+void (*glXGetProcAddressARB(const GLubyte *procName))();
+void (*glXGetProcAddressEXT(const GLubyte *procName))();
+
+// We support four different ways for getting addresses for GL/GLX
+// extension functions: glXGetProcAddress, glXGetProcAddressARB,
+// glXGetProcAddressEXT, and dlsym
+#if defined( _GLFW_HAS_GLXGETPROCADDRESSARB )
+ #define _glfw_glXGetProcAddress(x) glXGetProcAddressARB(x)
+#elif defined( _GLFW_HAS_GLXGETPROCADDRESS )
+ #define _glfw_glXGetProcAddress(x) glXGetProcAddress(x)
+#elif defined( _GLFW_HAS_GLXGETPROCADDRESSEXT )
+ #define _glfw_glXGetProcAddress(x) glXGetProcAddressEXT(x)
+#elif defined( _GLFW_HAS_DLOPEN )
+ #define _glfw_glXGetProcAddress(x) dlsym(_glfwLibs.libGL,x)
+ #define _GLFW_DLOPEN_LIBGL
+#else
+#define _glfw_glXGetProcAddress(x) NULL
+#endif
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Check if an OpenGL extension is available at runtime
+//========================================================================
+
+int _glfwPlatformExtensionSupported( const char *extension )
+{
+ const GLubyte *extensions;
+
+ // Get list of GLX extensions
+ extensions = (const GLubyte*) glXQueryExtensionsString( _glfwLibrary.display,
+ _glfwWin.screen );
+ if( extensions != NULL )
+ {
+ if( _glfwStringInExtensionString( extension, extensions ) )
+ {
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+
+//========================================================================
+// Get the function pointer to an OpenGL function
+//========================================================================
+
+void * _glfwPlatformGetProcAddress( const char *procname )
+{
+ return (void *) _glfw_glXGetProcAddress( (const GLubyte *) procname );
+}
+
diff --git a/lib/x11/x11_init.c b/lib/x11/x11_init.c
new file mode 100644
index 00000000..612a524f
--- /dev/null
+++ b/lib/x11/x11_init.c
@@ -0,0 +1,206 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: X11/GLX
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+//========================================================================
+// Dynamically load libraries
+//========================================================================
+
+static void initLibraries( void )
+{
+#ifdef _GLFW_DLOPEN_LIBGL
+ int i;
+ char *libGL_names[ ] =
+ {
+ "libGL.so",
+ "libGL.so.1",
+ "/usr/lib/libGL.so",
+ "/usr/lib/libGL.so.1",
+ NULL
+ };
+
+ _glfwLibrary.Libs.libGL = NULL;
+ for( i = 0; !libGL_names[ i ] != NULL; i ++ )
+ {
+ _glfwLibrary.Libs.libGL = dlopen( libGL_names[ i ],
+ RTLD_LAZY | RTLD_GLOBAL );
+ if( _glfwLibrary.Libs.libGL )
+ break;
+ }
+#endif
+}
+
+
+//========================================================================
+// Terminate GLFW when exiting application
+//========================================================================
+
+static void glfw_atexit( void )
+{
+ glfwTerminate();
+}
+
+
+//========================================================================
+// Initialize X11 display
+//========================================================================
+
+static int initDisplay( void )
+{
+ // Open display
+ _glfwLibrary.display = XOpenDisplay( 0 );
+ if( !_glfwLibrary.display )
+ {
+ fprintf(stderr, "Failed to open X display\n");
+ return GL_FALSE;
+ }
+
+ // Check for XF86VidMode extension
+#ifdef _GLFW_HAS_XF86VIDMODE
+ _glfwLibrary.XF86VidMode.available =
+ XF86VidModeQueryExtension( _glfwLibrary.display,
+ &_glfwLibrary.XF86VidMode.eventBase,
+ &_glfwLibrary.XF86VidMode.errorBase);
+#else
+ _glfwLibrary.XF86VidMode.available = 0;
+#endif
+
+ // Check for XRandR extension
+#ifdef _GLFW_HAS_XRANDR
+ _glfwLibrary.XRandR.available =
+ XRRQueryExtension( _glfwLibrary.display,
+ &_glfwLibrary.XRandR.eventBase,
+ &_glfwLibrary.XRandR.errorBase );
+#else
+ _glfwLibrary.XRandR.available = 0;
+#endif
+
+ // Fullscreen & screen saver settings
+ // Check if GLX is supported on this display
+ if( !glXQueryExtension( _glfwLibrary.display, NULL, NULL ) )
+ {
+ fprintf(stderr, "GLX not supported\n");
+ return GL_FALSE;
+ }
+
+ // Retrieve GLX version
+ if( !glXQueryVersion( _glfwLibrary.display,
+ &_glfwLibrary.glxMajor,
+ &_glfwLibrary.glxMinor ) )
+ {
+ fprintf(stderr, "Unable to query GLX version\n");
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+//========================================================================
+// Terminate X11 display
+//========================================================================
+
+static void terminateDisplay( void )
+{
+ // Open display
+ if( _glfwLibrary.display )
+ {
+ XCloseDisplay( _glfwLibrary.display );
+ _glfwLibrary.display = NULL;
+ }
+}
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Initialize various GLFW state
+//========================================================================
+
+int _glfwPlatformInit( void )
+{
+ // Initialize display
+ if( !initDisplay() )
+ {
+ return GL_FALSE;
+ }
+
+ // Try to load libGL.so if necessary
+ initLibraries();
+
+ // Install atexit() routine
+ atexit( glfw_atexit );
+
+ // Initialize joysticks
+ _glfwInitJoysticks();
+
+ // Start the timer
+ _glfwInitTimer();
+
+ return GL_TRUE;
+}
+
+
+//========================================================================
+// Close window and shut down library
+//========================================================================
+
+int _glfwPlatformTerminate( void )
+{
+ // Close OpenGL window
+ glfwCloseWindow();
+
+ // Terminate display
+ terminateDisplay();
+
+ // Terminate joysticks
+ _glfwTerminateJoysticks();
+
+ // Unload libGL.so if necessary
+#ifdef _GLFW_DLOPEN_LIBGL
+ if( _glfwLibrary.Libs.libGL != NULL )
+ {
+ dlclose( _glfwLibrary.Libs.libGL );
+ _glfwLibrary.Libs.libGL = NULL;
+ }
+#endif
+
+ return GL_TRUE;
+}
+
diff --git a/lib/x11/x11_joystick.c b/lib/x11/x11_joystick.c
new file mode 100644
index 00000000..90c9c648
--- /dev/null
+++ b/lib/x11/x11_joystick.c
@@ -0,0 +1,367 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: X11/GLX
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+//========================================================================
+// Note: Only Linux joystick input is supported at the moment. Other
+// systems will behave as if there are no joysticks connected.
+//========================================================================
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+#ifdef _GLFW_USE_LINUX_JOYSTICKS
+
+//------------------------------------------------------------------------
+// Here are the Linux joystick driver v1.x interface definitions that we
+// use (we do not want to rely on ):
+//------------------------------------------------------------------------
+
+#include
+#include
+#include
+
+// Joystick event types
+#define JS_EVENT_BUTTON 0x01 /* button pressed/released */
+#define JS_EVENT_AXIS 0x02 /* joystick moved */
+#define JS_EVENT_INIT 0x80 /* initial state of device */
+
+// Joystick event structure
+struct js_event {
+ unsigned int time; /* (u32) event timestamp in milliseconds */
+ signed short value; /* (s16) value */
+ unsigned char type; /* (u8) event type */
+ unsigned char number; /* (u8) axis/button number */
+};
+
+// Joystick IOCTL commands
+#define JSIOCGVERSION _IOR('j', 0x01, int) /* get driver version (u32) */
+#define JSIOCGAXES _IOR('j', 0x11, char) /* get number of axes (u8) */
+#define JSIOCGBUTTONS _IOR('j', 0x12, char) /* get number of buttons (u8) */
+
+#endif // _GLFW_USE_LINUX_JOYSTICKS
+
+
+//========================================================================
+// _glfwInitJoysticks() - Initialize joystick interface
+//========================================================================
+
+void _glfwInitJoysticks( void )
+{
+#ifdef _GLFW_USE_LINUX_JOYSTICKS
+ int k, n, fd, joy_count;
+ char *joy_base_name, joy_dev_name[ 20 ];
+ int driver_version = 0x000800;
+ char ret_data;
+#endif // _GLFW_USE_LINUX_JOYSTICKS
+ int i;
+
+ // Start by saying that there are no sticks
+ for( i = 0; i <= GLFW_JOYSTICK_LAST; ++ i )
+ {
+ _glfwJoy[ i ].Present = GL_FALSE;
+ }
+
+#ifdef _GLFW_USE_LINUX_JOYSTICKS
+
+ // Try to open joysticks (nonblocking)
+ joy_count = 0;
+ for( k = 0; k <= 1 && joy_count <= GLFW_JOYSTICK_LAST; ++ k )
+ {
+ // Pick joystick base name
+ switch( k )
+ {
+ case 0:
+ joy_base_name = "/dev/input/js"; // USB sticks
+ break;
+ case 1:
+ joy_base_name = "/dev/js"; // "Legacy" sticks
+ break;
+ default:
+ continue; // (should never happen)
+ }
+
+ // Try to open a few of these sticks
+ for( i = 0; i <= 50 && joy_count <= GLFW_JOYSTICK_LAST; ++ i )
+ {
+ sprintf( joy_dev_name, "%s%d", joy_base_name, i );
+ fd = open( joy_dev_name, O_NONBLOCK );
+ if( fd != -1 )
+ {
+ // Remember fd
+ _glfwJoy[ joy_count ].fd = fd;
+
+ // Check that the joystick driver version is 1.0+
+ ioctl( fd, JSIOCGVERSION, &driver_version );
+ if( driver_version < 0x010000 )
+ {
+ // It's an old 0.x interface (we don't support it)
+ close( fd );
+ continue;
+ }
+
+ // Get number of joystick axes
+ ioctl( fd, JSIOCGAXES, &ret_data );
+ _glfwJoy[ joy_count ].NumAxes = (int) ret_data;
+
+ // Get number of joystick buttons
+ ioctl( fd, JSIOCGBUTTONS, &ret_data );
+ _glfwJoy[ joy_count ].NumButtons = (int) ret_data;
+
+ // Allocate memory for joystick state
+ _glfwJoy[ joy_count ].Axis =
+ (float *) malloc( sizeof(float) *
+ _glfwJoy[ joy_count ].NumAxes );
+ if( _glfwJoy[ joy_count ].Axis == NULL )
+ {
+ close( fd );
+ continue;
+ }
+ _glfwJoy[ joy_count ].Button =
+ (unsigned char *) malloc( sizeof(char) *
+ _glfwJoy[ joy_count ].NumButtons );
+ if( _glfwJoy[ joy_count ].Button == NULL )
+ {
+ free( _glfwJoy[ joy_count ].Axis );
+ close( fd );
+ continue;
+ }
+
+ // Clear joystick state
+ for( n = 0; n < _glfwJoy[ joy_count ].NumAxes; ++ n )
+ {
+ _glfwJoy[ joy_count ].Axis[ n ] = 0.0f;
+ }
+ for( n = 0; n < _glfwJoy[ joy_count ].NumButtons; ++ n )
+ {
+ _glfwJoy[ joy_count ].Button[ n ] = GLFW_RELEASE;
+ }
+
+ // The joystick is supported and connected
+ _glfwJoy[ joy_count ].Present = GL_TRUE;
+ joy_count ++;
+ }
+ }
+ }
+
+#endif // _GLFW_USE_LINUX_JOYSTICKS
+
+}
+
+
+//========================================================================
+// _glfwTerminateJoysticks() - Close all opened joystick handles
+//========================================================================
+
+void _glfwTerminateJoysticks( void )
+{
+
+#ifdef _GLFW_USE_LINUX_JOYSTICKS
+
+ int i;
+
+ // Close any opened joysticks
+ for( i = 0; i <= GLFW_JOYSTICK_LAST; ++ i )
+ {
+ if( _glfwJoy[ i ].Present )
+ {
+ close( _glfwJoy[ i ].fd );
+ free( _glfwJoy[ i ].Axis );
+ free( _glfwJoy[ i ].Button );
+ _glfwJoy[ i ].Present = GL_FALSE;
+ }
+ }
+
+#endif // _GLFW_USE_LINUX_JOYSTICKS
+
+}
+
+
+//========================================================================
+// Empty joystick event queue
+//========================================================================
+
+static void pollJoystickEvents( void )
+{
+
+#ifdef _GLFW_USE_LINUX_JOYSTICKS
+
+ struct js_event e;
+ int i;
+
+ // Get joystick events for all GLFW joysticks
+ for( i = 0; i <= GLFW_JOYSTICK_LAST; ++ i )
+ {
+ // Is the stick present?
+ if( _glfwJoy[ i ].Present )
+ {
+ // Read all queued events (non-blocking)
+ while( read(_glfwJoy[i].fd, &e, sizeof(struct js_event)) > 0 )
+ {
+ // We don't care if it's an init event or not
+ e.type &= ~JS_EVENT_INIT;
+
+ // Check event type
+ switch( e.type )
+ {
+ case JS_EVENT_AXIS:
+ _glfwJoy[ i ].Axis[ e.number ] = (float) e.value /
+ 32767.0f;
+ // We need to change the sign for the Y axes, so that
+ // positive = up/forward, according to the GLFW spec.
+ if( e.number & 1 )
+ {
+ _glfwJoy[ i ].Axis[ e.number ] =
+ -_glfwJoy[ i ].Axis[ e.number ];
+ }
+ break;
+
+ case JS_EVENT_BUTTON:
+ _glfwJoy[ i ].Button[ e.number ] =
+ e.value ? GLFW_PRESS : GLFW_RELEASE;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+#endif // _GLFW_USE_LINUX_JOYSTICKS
+
+}
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// _glfwPlatformGetJoystickParam() - Determine joystick capabilities
+//========================================================================
+
+int _glfwPlatformGetJoystickParam( int joy, int param )
+{
+ // Is joystick present?
+ if( !_glfwJoy[ joy ].Present )
+ {
+ return 0;
+ }
+
+ switch( param )
+ {
+ case GLFW_PRESENT:
+ return GL_TRUE;
+
+ case GLFW_AXES:
+ return _glfwJoy[ joy ].NumAxes;
+
+ case GLFW_BUTTONS:
+ return _glfwJoy[ joy ].NumButtons;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+//========================================================================
+// _glfwPlatformGetJoystickPos() - Get joystick axis positions
+//========================================================================
+
+int _glfwPlatformGetJoystickPos( int joy, float *pos, int numaxes )
+{
+ int i;
+
+ // Is joystick present?
+ if( !_glfwJoy[ joy ].Present )
+ {
+ return 0;
+ }
+
+ // Update joystick state
+ pollJoystickEvents();
+
+ // Does the joystick support less axes than requested?
+ if( _glfwJoy[ joy ].NumAxes < numaxes )
+ {
+ numaxes = _glfwJoy[ joy ].NumAxes;
+ }
+
+ // Copy axis positions from internal state
+ for( i = 0; i < numaxes; ++ i )
+ {
+ pos[ i ] = _glfwJoy[ joy ].Axis[ i ];
+ }
+
+ return numaxes;
+}
+
+
+//========================================================================
+// _glfwPlatformGetJoystickButtons() - Get joystick button states
+//========================================================================
+
+int _glfwPlatformGetJoystickButtons( int joy, unsigned char *buttons,
+ int numbuttons )
+{
+ int i;
+
+ // Is joystick present?
+ if( !_glfwJoy[ joy ].Present )
+ {
+ return 0;
+ }
+
+ // Update joystick state
+ pollJoystickEvents();
+
+ // Does the joystick support less buttons than requested?
+ if( _glfwJoy[ joy ].NumButtons < numbuttons )
+ {
+ numbuttons = _glfwJoy[ joy ].NumButtons;
+ }
+
+ // Copy button states from internal state
+ for( i = 0; i < numbuttons; ++ i )
+ {
+ buttons[ i ] = _glfwJoy[ joy ].Button[ i ];
+ }
+
+ return numbuttons;
+}
+
diff --git a/lib/x11/x11_keysym2unicode.c b/lib/x11/x11_keysym2unicode.c
new file mode 100644
index 00000000..9701cb49
--- /dev/null
+++ b/lib/x11/x11_keysym2unicode.c
@@ -0,0 +1,901 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: X11/GLX
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+/*
+ * Marcus: This code was originally written by Markus G. Kuhn.
+ * I have made some slight changes (trimmed it down a bit from >60 KB to
+ * 20 KB), but the functionality is the same.
+ */
+
+/*
+ * This module converts keysym values into the corresponding ISO 10646
+ * (UCS, Unicode) values.
+ *
+ * The array keysymtab[] contains pairs of X11 keysym values for graphical
+ * characters and the corresponding Unicode value. The function
+ * _glfwKeySym2Unicode() maps a keysym onto a Unicode value using a binary
+ * search, therefore keysymtab[] must remain SORTED by keysym value.
+ *
+ * We allow to represent any UCS character in the range U-00000000 to
+ * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
+ * This admittedly does not cover the entire 31-bit space of UCS, but
+ * it does cover all of the characters up to U-10FFFF, which can be
+ * represented by UTF-16, and more, and it is very unlikely that higher
+ * UCS codes will ever be assigned by ISO. So to get Unicode character
+ * U+ABCD you can directly use keysym 0x0100abcd.
+ *
+ * Original author: Markus G. Kuhn , University of
+ * Cambridge, April 2001
+ *
+ * Special thanks to Richard Verhoeven for preparing
+ * an initial draft of the mapping table.
+ *
+ */
+
+
+//************************************************************************
+//**** KeySym to Unicode mapping table ****
+//************************************************************************
+
+static struct codepair {
+ unsigned short keysym;
+ unsigned short ucs;
+} keysymtab[] = {
+ { 0x01a1, 0x0104 },
+ { 0x01a2, 0x02d8 },
+ { 0x01a3, 0x0141 },
+ { 0x01a5, 0x013d },
+ { 0x01a6, 0x015a },
+ { 0x01a9, 0x0160 },
+ { 0x01aa, 0x015e },
+ { 0x01ab, 0x0164 },
+ { 0x01ac, 0x0179 },
+ { 0x01ae, 0x017d },
+ { 0x01af, 0x017b },
+ { 0x01b1, 0x0105 },
+ { 0x01b2, 0x02db },
+ { 0x01b3, 0x0142 },
+ { 0x01b5, 0x013e },
+ { 0x01b6, 0x015b },
+ { 0x01b7, 0x02c7 },
+ { 0x01b9, 0x0161 },
+ { 0x01ba, 0x015f },
+ { 0x01bb, 0x0165 },
+ { 0x01bc, 0x017a },
+ { 0x01bd, 0x02dd },
+ { 0x01be, 0x017e },
+ { 0x01bf, 0x017c },
+ { 0x01c0, 0x0154 },
+ { 0x01c3, 0x0102 },
+ { 0x01c5, 0x0139 },
+ { 0x01c6, 0x0106 },
+ { 0x01c8, 0x010c },
+ { 0x01ca, 0x0118 },
+ { 0x01cc, 0x011a },
+ { 0x01cf, 0x010e },
+ { 0x01d0, 0x0110 },
+ { 0x01d1, 0x0143 },
+ { 0x01d2, 0x0147 },
+ { 0x01d5, 0x0150 },
+ { 0x01d8, 0x0158 },
+ { 0x01d9, 0x016e },
+ { 0x01db, 0x0170 },
+ { 0x01de, 0x0162 },
+ { 0x01e0, 0x0155 },
+ { 0x01e3, 0x0103 },
+ { 0x01e5, 0x013a },
+ { 0x01e6, 0x0107 },
+ { 0x01e8, 0x010d },
+ { 0x01ea, 0x0119 },
+ { 0x01ec, 0x011b },
+ { 0x01ef, 0x010f },
+ { 0x01f0, 0x0111 },
+ { 0x01f1, 0x0144 },
+ { 0x01f2, 0x0148 },
+ { 0x01f5, 0x0151 },
+ { 0x01f8, 0x0159 },
+ { 0x01f9, 0x016f },
+ { 0x01fb, 0x0171 },
+ { 0x01fe, 0x0163 },
+ { 0x01ff, 0x02d9 },
+ { 0x02a1, 0x0126 },
+ { 0x02a6, 0x0124 },
+ { 0x02a9, 0x0130 },
+ { 0x02ab, 0x011e },
+ { 0x02ac, 0x0134 },
+ { 0x02b1, 0x0127 },
+ { 0x02b6, 0x0125 },
+ { 0x02b9, 0x0131 },
+ { 0x02bb, 0x011f },
+ { 0x02bc, 0x0135 },
+ { 0x02c5, 0x010a },
+ { 0x02c6, 0x0108 },
+ { 0x02d5, 0x0120 },
+ { 0x02d8, 0x011c },
+ { 0x02dd, 0x016c },
+ { 0x02de, 0x015c },
+ { 0x02e5, 0x010b },
+ { 0x02e6, 0x0109 },
+ { 0x02f5, 0x0121 },
+ { 0x02f8, 0x011d },
+ { 0x02fd, 0x016d },
+ { 0x02fe, 0x015d },
+ { 0x03a2, 0x0138 },
+ { 0x03a3, 0x0156 },
+ { 0x03a5, 0x0128 },
+ { 0x03a6, 0x013b },
+ { 0x03aa, 0x0112 },
+ { 0x03ab, 0x0122 },
+ { 0x03ac, 0x0166 },
+ { 0x03b3, 0x0157 },
+ { 0x03b5, 0x0129 },
+ { 0x03b6, 0x013c },
+ { 0x03ba, 0x0113 },
+ { 0x03bb, 0x0123 },
+ { 0x03bc, 0x0167 },
+ { 0x03bd, 0x014a },
+ { 0x03bf, 0x014b },
+ { 0x03c0, 0x0100 },
+ { 0x03c7, 0x012e },
+ { 0x03cc, 0x0116 },
+ { 0x03cf, 0x012a },
+ { 0x03d1, 0x0145 },
+ { 0x03d2, 0x014c },
+ { 0x03d3, 0x0136 },
+ { 0x03d9, 0x0172 },
+ { 0x03dd, 0x0168 },
+ { 0x03de, 0x016a },
+ { 0x03e0, 0x0101 },
+ { 0x03e7, 0x012f },
+ { 0x03ec, 0x0117 },
+ { 0x03ef, 0x012b },
+ { 0x03f1, 0x0146 },
+ { 0x03f2, 0x014d },
+ { 0x03f3, 0x0137 },
+ { 0x03f9, 0x0173 },
+ { 0x03fd, 0x0169 },
+ { 0x03fe, 0x016b },
+ { 0x047e, 0x203e },
+ { 0x04a1, 0x3002 },
+ { 0x04a2, 0x300c },
+ { 0x04a3, 0x300d },
+ { 0x04a4, 0x3001 },
+ { 0x04a5, 0x30fb },
+ { 0x04a6, 0x30f2 },
+ { 0x04a7, 0x30a1 },
+ { 0x04a8, 0x30a3 },
+ { 0x04a9, 0x30a5 },
+ { 0x04aa, 0x30a7 },
+ { 0x04ab, 0x30a9 },
+ { 0x04ac, 0x30e3 },
+ { 0x04ad, 0x30e5 },
+ { 0x04ae, 0x30e7 },
+ { 0x04af, 0x30c3 },
+ { 0x04b0, 0x30fc },
+ { 0x04b1, 0x30a2 },
+ { 0x04b2, 0x30a4 },
+ { 0x04b3, 0x30a6 },
+ { 0x04b4, 0x30a8 },
+ { 0x04b5, 0x30aa },
+ { 0x04b6, 0x30ab },
+ { 0x04b7, 0x30ad },
+ { 0x04b8, 0x30af },
+ { 0x04b9, 0x30b1 },
+ { 0x04ba, 0x30b3 },
+ { 0x04bb, 0x30b5 },
+ { 0x04bc, 0x30b7 },
+ { 0x04bd, 0x30b9 },
+ { 0x04be, 0x30bb },
+ { 0x04bf, 0x30bd },
+ { 0x04c0, 0x30bf },
+ { 0x04c1, 0x30c1 },
+ { 0x04c2, 0x30c4 },
+ { 0x04c3, 0x30c6 },
+ { 0x04c4, 0x30c8 },
+ { 0x04c5, 0x30ca },
+ { 0x04c6, 0x30cb },
+ { 0x04c7, 0x30cc },
+ { 0x04c8, 0x30cd },
+ { 0x04c9, 0x30ce },
+ { 0x04ca, 0x30cf },
+ { 0x04cb, 0x30d2 },
+ { 0x04cc, 0x30d5 },
+ { 0x04cd, 0x30d8 },
+ { 0x04ce, 0x30db },
+ { 0x04cf, 0x30de },
+ { 0x04d0, 0x30df },
+ { 0x04d1, 0x30e0 },
+ { 0x04d2, 0x30e1 },
+ { 0x04d3, 0x30e2 },
+ { 0x04d4, 0x30e4 },
+ { 0x04d5, 0x30e6 },
+ { 0x04d6, 0x30e8 },
+ { 0x04d7, 0x30e9 },
+ { 0x04d8, 0x30ea },
+ { 0x04d9, 0x30eb },
+ { 0x04da, 0x30ec },
+ { 0x04db, 0x30ed },
+ { 0x04dc, 0x30ef },
+ { 0x04dd, 0x30f3 },
+ { 0x04de, 0x309b },
+ { 0x04df, 0x309c },
+ { 0x05ac, 0x060c },
+ { 0x05bb, 0x061b },
+ { 0x05bf, 0x061f },
+ { 0x05c1, 0x0621 },
+ { 0x05c2, 0x0622 },
+ { 0x05c3, 0x0623 },
+ { 0x05c4, 0x0624 },
+ { 0x05c5, 0x0625 },
+ { 0x05c6, 0x0626 },
+ { 0x05c7, 0x0627 },
+ { 0x05c8, 0x0628 },
+ { 0x05c9, 0x0629 },
+ { 0x05ca, 0x062a },
+ { 0x05cb, 0x062b },
+ { 0x05cc, 0x062c },
+ { 0x05cd, 0x062d },
+ { 0x05ce, 0x062e },
+ { 0x05cf, 0x062f },
+ { 0x05d0, 0x0630 },
+ { 0x05d1, 0x0631 },
+ { 0x05d2, 0x0632 },
+ { 0x05d3, 0x0633 },
+ { 0x05d4, 0x0634 },
+ { 0x05d5, 0x0635 },
+ { 0x05d6, 0x0636 },
+ { 0x05d7, 0x0637 },
+ { 0x05d8, 0x0638 },
+ { 0x05d9, 0x0639 },
+ { 0x05da, 0x063a },
+ { 0x05e0, 0x0640 },
+ { 0x05e1, 0x0641 },
+ { 0x05e2, 0x0642 },
+ { 0x05e3, 0x0643 },
+ { 0x05e4, 0x0644 },
+ { 0x05e5, 0x0645 },
+ { 0x05e6, 0x0646 },
+ { 0x05e7, 0x0647 },
+ { 0x05e8, 0x0648 },
+ { 0x05e9, 0x0649 },
+ { 0x05ea, 0x064a },
+ { 0x05eb, 0x064b },
+ { 0x05ec, 0x064c },
+ { 0x05ed, 0x064d },
+ { 0x05ee, 0x064e },
+ { 0x05ef, 0x064f },
+ { 0x05f0, 0x0650 },
+ { 0x05f1, 0x0651 },
+ { 0x05f2, 0x0652 },
+ { 0x06a1, 0x0452 },
+ { 0x06a2, 0x0453 },
+ { 0x06a3, 0x0451 },
+ { 0x06a4, 0x0454 },
+ { 0x06a5, 0x0455 },
+ { 0x06a6, 0x0456 },
+ { 0x06a7, 0x0457 },
+ { 0x06a8, 0x0458 },
+ { 0x06a9, 0x0459 },
+ { 0x06aa, 0x045a },
+ { 0x06ab, 0x045b },
+ { 0x06ac, 0x045c },
+ { 0x06ae, 0x045e },
+ { 0x06af, 0x045f },
+ { 0x06b0, 0x2116 },
+ { 0x06b1, 0x0402 },
+ { 0x06b2, 0x0403 },
+ { 0x06b3, 0x0401 },
+ { 0x06b4, 0x0404 },
+ { 0x06b5, 0x0405 },
+ { 0x06b6, 0x0406 },
+ { 0x06b7, 0x0407 },
+ { 0x06b8, 0x0408 },
+ { 0x06b9, 0x0409 },
+ { 0x06ba, 0x040a },
+ { 0x06bb, 0x040b },
+ { 0x06bc, 0x040c },
+ { 0x06be, 0x040e },
+ { 0x06bf, 0x040f },
+ { 0x06c0, 0x044e },
+ { 0x06c1, 0x0430 },
+ { 0x06c2, 0x0431 },
+ { 0x06c3, 0x0446 },
+ { 0x06c4, 0x0434 },
+ { 0x06c5, 0x0435 },
+ { 0x06c6, 0x0444 },
+ { 0x06c7, 0x0433 },
+ { 0x06c8, 0x0445 },
+ { 0x06c9, 0x0438 },
+ { 0x06ca, 0x0439 },
+ { 0x06cb, 0x043a },
+ { 0x06cc, 0x043b },
+ { 0x06cd, 0x043c },
+ { 0x06ce, 0x043d },
+ { 0x06cf, 0x043e },
+ { 0x06d0, 0x043f },
+ { 0x06d1, 0x044f },
+ { 0x06d2, 0x0440 },
+ { 0x06d3, 0x0441 },
+ { 0x06d4, 0x0442 },
+ { 0x06d5, 0x0443 },
+ { 0x06d6, 0x0436 },
+ { 0x06d7, 0x0432 },
+ { 0x06d8, 0x044c },
+ { 0x06d9, 0x044b },
+ { 0x06da, 0x0437 },
+ { 0x06db, 0x0448 },
+ { 0x06dc, 0x044d },
+ { 0x06dd, 0x0449 },
+ { 0x06de, 0x0447 },
+ { 0x06df, 0x044a },
+ { 0x06e0, 0x042e },
+ { 0x06e1, 0x0410 },
+ { 0x06e2, 0x0411 },
+ { 0x06e3, 0x0426 },
+ { 0x06e4, 0x0414 },
+ { 0x06e5, 0x0415 },
+ { 0x06e6, 0x0424 },
+ { 0x06e7, 0x0413 },
+ { 0x06e8, 0x0425 },
+ { 0x06e9, 0x0418 },
+ { 0x06ea, 0x0419 },
+ { 0x06eb, 0x041a },
+ { 0x06ec, 0x041b },
+ { 0x06ed, 0x041c },
+ { 0x06ee, 0x041d },
+ { 0x06ef, 0x041e },
+ { 0x06f0, 0x041f },
+ { 0x06f1, 0x042f },
+ { 0x06f2, 0x0420 },
+ { 0x06f3, 0x0421 },
+ { 0x06f4, 0x0422 },
+ { 0x06f5, 0x0423 },
+ { 0x06f6, 0x0416 },
+ { 0x06f7, 0x0412 },
+ { 0x06f8, 0x042c },
+ { 0x06f9, 0x042b },
+ { 0x06fa, 0x0417 },
+ { 0x06fb, 0x0428 },
+ { 0x06fc, 0x042d },
+ { 0x06fd, 0x0429 },
+ { 0x06fe, 0x0427 },
+ { 0x06ff, 0x042a },
+ { 0x07a1, 0x0386 },
+ { 0x07a2, 0x0388 },
+ { 0x07a3, 0x0389 },
+ { 0x07a4, 0x038a },
+ { 0x07a5, 0x03aa },
+ { 0x07a7, 0x038c },
+ { 0x07a8, 0x038e },
+ { 0x07a9, 0x03ab },
+ { 0x07ab, 0x038f },
+ { 0x07ae, 0x0385 },
+ { 0x07af, 0x2015 },
+ { 0x07b1, 0x03ac },
+ { 0x07b2, 0x03ad },
+ { 0x07b3, 0x03ae },
+ { 0x07b4, 0x03af },
+ { 0x07b5, 0x03ca },
+ { 0x07b6, 0x0390 },
+ { 0x07b7, 0x03cc },
+ { 0x07b8, 0x03cd },
+ { 0x07b9, 0x03cb },
+ { 0x07ba, 0x03b0 },
+ { 0x07bb, 0x03ce },
+ { 0x07c1, 0x0391 },
+ { 0x07c2, 0x0392 },
+ { 0x07c3, 0x0393 },
+ { 0x07c4, 0x0394 },
+ { 0x07c5, 0x0395 },
+ { 0x07c6, 0x0396 },
+ { 0x07c7, 0x0397 },
+ { 0x07c8, 0x0398 },
+ { 0x07c9, 0x0399 },
+ { 0x07ca, 0x039a },
+ { 0x07cb, 0x039b },
+ { 0x07cc, 0x039c },
+ { 0x07cd, 0x039d },
+ { 0x07ce, 0x039e },
+ { 0x07cf, 0x039f },
+ { 0x07d0, 0x03a0 },
+ { 0x07d1, 0x03a1 },
+ { 0x07d2, 0x03a3 },
+ { 0x07d4, 0x03a4 },
+ { 0x07d5, 0x03a5 },
+ { 0x07d6, 0x03a6 },
+ { 0x07d7, 0x03a7 },
+ { 0x07d8, 0x03a8 },
+ { 0x07d9, 0x03a9 },
+ { 0x07e1, 0x03b1 },
+ { 0x07e2, 0x03b2 },
+ { 0x07e3, 0x03b3 },
+ { 0x07e4, 0x03b4 },
+ { 0x07e5, 0x03b5 },
+ { 0x07e6, 0x03b6 },
+ { 0x07e7, 0x03b7 },
+ { 0x07e8, 0x03b8 },
+ { 0x07e9, 0x03b9 },
+ { 0x07ea, 0x03ba },
+ { 0x07eb, 0x03bb },
+ { 0x07ec, 0x03bc },
+ { 0x07ed, 0x03bd },
+ { 0x07ee, 0x03be },
+ { 0x07ef, 0x03bf },
+ { 0x07f0, 0x03c0 },
+ { 0x07f1, 0x03c1 },
+ { 0x07f2, 0x03c3 },
+ { 0x07f3, 0x03c2 },
+ { 0x07f4, 0x03c4 },
+ { 0x07f5, 0x03c5 },
+ { 0x07f6, 0x03c6 },
+ { 0x07f7, 0x03c7 },
+ { 0x07f8, 0x03c8 },
+ { 0x07f9, 0x03c9 },
+ { 0x08a1, 0x23b7 },
+ { 0x08a2, 0x250c },
+ { 0x08a3, 0x2500 },
+ { 0x08a4, 0x2320 },
+ { 0x08a5, 0x2321 },
+ { 0x08a6, 0x2502 },
+ { 0x08a7, 0x23a1 },
+ { 0x08a8, 0x23a3 },
+ { 0x08a9, 0x23a4 },
+ { 0x08aa, 0x23a6 },
+ { 0x08ab, 0x239b },
+ { 0x08ac, 0x239d },
+ { 0x08ad, 0x239e },
+ { 0x08ae, 0x23a0 },
+ { 0x08af, 0x23a8 },
+ { 0x08b0, 0x23ac },
+ { 0x08bc, 0x2264 },
+ { 0x08bd, 0x2260 },
+ { 0x08be, 0x2265 },
+ { 0x08bf, 0x222b },
+ { 0x08c0, 0x2234 },
+ { 0x08c1, 0x221d },
+ { 0x08c2, 0x221e },
+ { 0x08c5, 0x2207 },
+ { 0x08c8, 0x223c },
+ { 0x08c9, 0x2243 },
+ { 0x08cd, 0x21d4 },
+ { 0x08ce, 0x21d2 },
+ { 0x08cf, 0x2261 },
+ { 0x08d6, 0x221a },
+ { 0x08da, 0x2282 },
+ { 0x08db, 0x2283 },
+ { 0x08dc, 0x2229 },
+ { 0x08dd, 0x222a },
+ { 0x08de, 0x2227 },
+ { 0x08df, 0x2228 },
+ { 0x08ef, 0x2202 },
+ { 0x08f6, 0x0192 },
+ { 0x08fb, 0x2190 },
+ { 0x08fc, 0x2191 },
+ { 0x08fd, 0x2192 },
+ { 0x08fe, 0x2193 },
+ { 0x09e0, 0x25c6 },
+ { 0x09e1, 0x2592 },
+ { 0x09e2, 0x2409 },
+ { 0x09e3, 0x240c },
+ { 0x09e4, 0x240d },
+ { 0x09e5, 0x240a },
+ { 0x09e8, 0x2424 },
+ { 0x09e9, 0x240b },
+ { 0x09ea, 0x2518 },
+ { 0x09eb, 0x2510 },
+ { 0x09ec, 0x250c },
+ { 0x09ed, 0x2514 },
+ { 0x09ee, 0x253c },
+ { 0x09ef, 0x23ba },
+ { 0x09f0, 0x23bb },
+ { 0x09f1, 0x2500 },
+ { 0x09f2, 0x23bc },
+ { 0x09f3, 0x23bd },
+ { 0x09f4, 0x251c },
+ { 0x09f5, 0x2524 },
+ { 0x09f6, 0x2534 },
+ { 0x09f7, 0x252c },
+ { 0x09f8, 0x2502 },
+ { 0x0aa1, 0x2003 },
+ { 0x0aa2, 0x2002 },
+ { 0x0aa3, 0x2004 },
+ { 0x0aa4, 0x2005 },
+ { 0x0aa5, 0x2007 },
+ { 0x0aa6, 0x2008 },
+ { 0x0aa7, 0x2009 },
+ { 0x0aa8, 0x200a },
+ { 0x0aa9, 0x2014 },
+ { 0x0aaa, 0x2013 },
+ { 0x0aae, 0x2026 },
+ { 0x0aaf, 0x2025 },
+ { 0x0ab0, 0x2153 },
+ { 0x0ab1, 0x2154 },
+ { 0x0ab2, 0x2155 },
+ { 0x0ab3, 0x2156 },
+ { 0x0ab4, 0x2157 },
+ { 0x0ab5, 0x2158 },
+ { 0x0ab6, 0x2159 },
+ { 0x0ab7, 0x215a },
+ { 0x0ab8, 0x2105 },
+ { 0x0abb, 0x2012 },
+ { 0x0abc, 0x2329 },
+ { 0x0abe, 0x232a },
+ { 0x0ac3, 0x215b },
+ { 0x0ac4, 0x215c },
+ { 0x0ac5, 0x215d },
+ { 0x0ac6, 0x215e },
+ { 0x0ac9, 0x2122 },
+ { 0x0aca, 0x2613 },
+ { 0x0acc, 0x25c1 },
+ { 0x0acd, 0x25b7 },
+ { 0x0ace, 0x25cb },
+ { 0x0acf, 0x25af },
+ { 0x0ad0, 0x2018 },
+ { 0x0ad1, 0x2019 },
+ { 0x0ad2, 0x201c },
+ { 0x0ad3, 0x201d },
+ { 0x0ad4, 0x211e },
+ { 0x0ad6, 0x2032 },
+ { 0x0ad7, 0x2033 },
+ { 0x0ad9, 0x271d },
+ { 0x0adb, 0x25ac },
+ { 0x0adc, 0x25c0 },
+ { 0x0add, 0x25b6 },
+ { 0x0ade, 0x25cf },
+ { 0x0adf, 0x25ae },
+ { 0x0ae0, 0x25e6 },
+ { 0x0ae1, 0x25ab },
+ { 0x0ae2, 0x25ad },
+ { 0x0ae3, 0x25b3 },
+ { 0x0ae4, 0x25bd },
+ { 0x0ae5, 0x2606 },
+ { 0x0ae6, 0x2022 },
+ { 0x0ae7, 0x25aa },
+ { 0x0ae8, 0x25b2 },
+ { 0x0ae9, 0x25bc },
+ { 0x0aea, 0x261c },
+ { 0x0aeb, 0x261e },
+ { 0x0aec, 0x2663 },
+ { 0x0aed, 0x2666 },
+ { 0x0aee, 0x2665 },
+ { 0x0af0, 0x2720 },
+ { 0x0af1, 0x2020 },
+ { 0x0af2, 0x2021 },
+ { 0x0af3, 0x2713 },
+ { 0x0af4, 0x2717 },
+ { 0x0af5, 0x266f },
+ { 0x0af6, 0x266d },
+ { 0x0af7, 0x2642 },
+ { 0x0af8, 0x2640 },
+ { 0x0af9, 0x260e },
+ { 0x0afa, 0x2315 },
+ { 0x0afb, 0x2117 },
+ { 0x0afc, 0x2038 },
+ { 0x0afd, 0x201a },
+ { 0x0afe, 0x201e },
+ { 0x0ba3, 0x003c },
+ { 0x0ba6, 0x003e },
+ { 0x0ba8, 0x2228 },
+ { 0x0ba9, 0x2227 },
+ { 0x0bc0, 0x00af },
+ { 0x0bc2, 0x22a5 },
+ { 0x0bc3, 0x2229 },
+ { 0x0bc4, 0x230a },
+ { 0x0bc6, 0x005f },
+ { 0x0bca, 0x2218 },
+ { 0x0bcc, 0x2395 },
+ { 0x0bce, 0x22a4 },
+ { 0x0bcf, 0x25cb },
+ { 0x0bd3, 0x2308 },
+ { 0x0bd6, 0x222a },
+ { 0x0bd8, 0x2283 },
+ { 0x0bda, 0x2282 },
+ { 0x0bdc, 0x22a2 },
+ { 0x0bfc, 0x22a3 },
+ { 0x0cdf, 0x2017 },
+ { 0x0ce0, 0x05d0 },
+ { 0x0ce1, 0x05d1 },
+ { 0x0ce2, 0x05d2 },
+ { 0x0ce3, 0x05d3 },
+ { 0x0ce4, 0x05d4 },
+ { 0x0ce5, 0x05d5 },
+ { 0x0ce6, 0x05d6 },
+ { 0x0ce7, 0x05d7 },
+ { 0x0ce8, 0x05d8 },
+ { 0x0ce9, 0x05d9 },
+ { 0x0cea, 0x05da },
+ { 0x0ceb, 0x05db },
+ { 0x0cec, 0x05dc },
+ { 0x0ced, 0x05dd },
+ { 0x0cee, 0x05de },
+ { 0x0cef, 0x05df },
+ { 0x0cf0, 0x05e0 },
+ { 0x0cf1, 0x05e1 },
+ { 0x0cf2, 0x05e2 },
+ { 0x0cf3, 0x05e3 },
+ { 0x0cf4, 0x05e4 },
+ { 0x0cf5, 0x05e5 },
+ { 0x0cf6, 0x05e6 },
+ { 0x0cf7, 0x05e7 },
+ { 0x0cf8, 0x05e8 },
+ { 0x0cf9, 0x05e9 },
+ { 0x0cfa, 0x05ea },
+ { 0x0da1, 0x0e01 },
+ { 0x0da2, 0x0e02 },
+ { 0x0da3, 0x0e03 },
+ { 0x0da4, 0x0e04 },
+ { 0x0da5, 0x0e05 },
+ { 0x0da6, 0x0e06 },
+ { 0x0da7, 0x0e07 },
+ { 0x0da8, 0x0e08 },
+ { 0x0da9, 0x0e09 },
+ { 0x0daa, 0x0e0a },
+ { 0x0dab, 0x0e0b },
+ { 0x0dac, 0x0e0c },
+ { 0x0dad, 0x0e0d },
+ { 0x0dae, 0x0e0e },
+ { 0x0daf, 0x0e0f },
+ { 0x0db0, 0x0e10 },
+ { 0x0db1, 0x0e11 },
+ { 0x0db2, 0x0e12 },
+ { 0x0db3, 0x0e13 },
+ { 0x0db4, 0x0e14 },
+ { 0x0db5, 0x0e15 },
+ { 0x0db6, 0x0e16 },
+ { 0x0db7, 0x0e17 },
+ { 0x0db8, 0x0e18 },
+ { 0x0db9, 0x0e19 },
+ { 0x0dba, 0x0e1a },
+ { 0x0dbb, 0x0e1b },
+ { 0x0dbc, 0x0e1c },
+ { 0x0dbd, 0x0e1d },
+ { 0x0dbe, 0x0e1e },
+ { 0x0dbf, 0x0e1f },
+ { 0x0dc0, 0x0e20 },
+ { 0x0dc1, 0x0e21 },
+ { 0x0dc2, 0x0e22 },
+ { 0x0dc3, 0x0e23 },
+ { 0x0dc4, 0x0e24 },
+ { 0x0dc5, 0x0e25 },
+ { 0x0dc6, 0x0e26 },
+ { 0x0dc7, 0x0e27 },
+ { 0x0dc8, 0x0e28 },
+ { 0x0dc9, 0x0e29 },
+ { 0x0dca, 0x0e2a },
+ { 0x0dcb, 0x0e2b },
+ { 0x0dcc, 0x0e2c },
+ { 0x0dcd, 0x0e2d },
+ { 0x0dce, 0x0e2e },
+ { 0x0dcf, 0x0e2f },
+ { 0x0dd0, 0x0e30 },
+ { 0x0dd1, 0x0e31 },
+ { 0x0dd2, 0x0e32 },
+ { 0x0dd3, 0x0e33 },
+ { 0x0dd4, 0x0e34 },
+ { 0x0dd5, 0x0e35 },
+ { 0x0dd6, 0x0e36 },
+ { 0x0dd7, 0x0e37 },
+ { 0x0dd8, 0x0e38 },
+ { 0x0dd9, 0x0e39 },
+ { 0x0dda, 0x0e3a },
+ { 0x0ddf, 0x0e3f },
+ { 0x0de0, 0x0e40 },
+ { 0x0de1, 0x0e41 },
+ { 0x0de2, 0x0e42 },
+ { 0x0de3, 0x0e43 },
+ { 0x0de4, 0x0e44 },
+ { 0x0de5, 0x0e45 },
+ { 0x0de6, 0x0e46 },
+ { 0x0de7, 0x0e47 },
+ { 0x0de8, 0x0e48 },
+ { 0x0de9, 0x0e49 },
+ { 0x0dea, 0x0e4a },
+ { 0x0deb, 0x0e4b },
+ { 0x0dec, 0x0e4c },
+ { 0x0ded, 0x0e4d },
+ { 0x0df0, 0x0e50 },
+ { 0x0df1, 0x0e51 },
+ { 0x0df2, 0x0e52 },
+ { 0x0df3, 0x0e53 },
+ { 0x0df4, 0x0e54 },
+ { 0x0df5, 0x0e55 },
+ { 0x0df6, 0x0e56 },
+ { 0x0df7, 0x0e57 },
+ { 0x0df8, 0x0e58 },
+ { 0x0df9, 0x0e59 },
+ { 0x0ea1, 0x3131 },
+ { 0x0ea2, 0x3132 },
+ { 0x0ea3, 0x3133 },
+ { 0x0ea4, 0x3134 },
+ { 0x0ea5, 0x3135 },
+ { 0x0ea6, 0x3136 },
+ { 0x0ea7, 0x3137 },
+ { 0x0ea8, 0x3138 },
+ { 0x0ea9, 0x3139 },
+ { 0x0eaa, 0x313a },
+ { 0x0eab, 0x313b },
+ { 0x0eac, 0x313c },
+ { 0x0ead, 0x313d },
+ { 0x0eae, 0x313e },
+ { 0x0eaf, 0x313f },
+ { 0x0eb0, 0x3140 },
+ { 0x0eb1, 0x3141 },
+ { 0x0eb2, 0x3142 },
+ { 0x0eb3, 0x3143 },
+ { 0x0eb4, 0x3144 },
+ { 0x0eb5, 0x3145 },
+ { 0x0eb6, 0x3146 },
+ { 0x0eb7, 0x3147 },
+ { 0x0eb8, 0x3148 },
+ { 0x0eb9, 0x3149 },
+ { 0x0eba, 0x314a },
+ { 0x0ebb, 0x314b },
+ { 0x0ebc, 0x314c },
+ { 0x0ebd, 0x314d },
+ { 0x0ebe, 0x314e },
+ { 0x0ebf, 0x314f },
+ { 0x0ec0, 0x3150 },
+ { 0x0ec1, 0x3151 },
+ { 0x0ec2, 0x3152 },
+ { 0x0ec3, 0x3153 },
+ { 0x0ec4, 0x3154 },
+ { 0x0ec5, 0x3155 },
+ { 0x0ec6, 0x3156 },
+ { 0x0ec7, 0x3157 },
+ { 0x0ec8, 0x3158 },
+ { 0x0ec9, 0x3159 },
+ { 0x0eca, 0x315a },
+ { 0x0ecb, 0x315b },
+ { 0x0ecc, 0x315c },
+ { 0x0ecd, 0x315d },
+ { 0x0ece, 0x315e },
+ { 0x0ecf, 0x315f },
+ { 0x0ed0, 0x3160 },
+ { 0x0ed1, 0x3161 },
+ { 0x0ed2, 0x3162 },
+ { 0x0ed3, 0x3163 },
+ { 0x0ed4, 0x11a8 },
+ { 0x0ed5, 0x11a9 },
+ { 0x0ed6, 0x11aa },
+ { 0x0ed7, 0x11ab },
+ { 0x0ed8, 0x11ac },
+ { 0x0ed9, 0x11ad },
+ { 0x0eda, 0x11ae },
+ { 0x0edb, 0x11af },
+ { 0x0edc, 0x11b0 },
+ { 0x0edd, 0x11b1 },
+ { 0x0ede, 0x11b2 },
+ { 0x0edf, 0x11b3 },
+ { 0x0ee0, 0x11b4 },
+ { 0x0ee1, 0x11b5 },
+ { 0x0ee2, 0x11b6 },
+ { 0x0ee3, 0x11b7 },
+ { 0x0ee4, 0x11b8 },
+ { 0x0ee5, 0x11b9 },
+ { 0x0ee6, 0x11ba },
+ { 0x0ee7, 0x11bb },
+ { 0x0ee8, 0x11bc },
+ { 0x0ee9, 0x11bd },
+ { 0x0eea, 0x11be },
+ { 0x0eeb, 0x11bf },
+ { 0x0eec, 0x11c0 },
+ { 0x0eed, 0x11c1 },
+ { 0x0eee, 0x11c2 },
+ { 0x0eef, 0x316d },
+ { 0x0ef0, 0x3171 },
+ { 0x0ef1, 0x3178 },
+ { 0x0ef2, 0x317f },
+ { 0x0ef3, 0x3181 },
+ { 0x0ef4, 0x3184 },
+ { 0x0ef5, 0x3186 },
+ { 0x0ef6, 0x318d },
+ { 0x0ef7, 0x318e },
+ { 0x0ef8, 0x11eb },
+ { 0x0ef9, 0x11f0 },
+ { 0x0efa, 0x11f9 },
+ { 0x0eff, 0x20a9 },
+ { 0x13a4, 0x20ac },
+ { 0x13bc, 0x0152 },
+ { 0x13bd, 0x0153 },
+ { 0x13be, 0x0178 },
+ { 0x20ac, 0x20ac },
+ // Numeric keypad with numlock on
+ { XK_KP_Space, ' ' },
+ { XK_KP_Equal, '=' },
+ { XK_KP_Multiply, '*' },
+ { XK_KP_Add, '+' },
+ { XK_KP_Separator, ',' },
+ { XK_KP_Subtract, '-' },
+ { XK_KP_Decimal, '.' },
+ { XK_KP_Divide, '/' },
+ { XK_KP_0, 0x0030 },
+ { XK_KP_1, 0x0031 },
+ { XK_KP_2, 0x0032 },
+ { XK_KP_3, 0x0033 },
+ { XK_KP_4, 0x0034 },
+ { XK_KP_5, 0x0035 },
+ { XK_KP_6, 0x0036 },
+ { XK_KP_7, 0x0037 },
+ { XK_KP_8, 0x0038 },
+ { XK_KP_9, 0x0039 }
+};
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+//========================================================================
+// _glfwKeySym2Unicode() - Convert X11 KeySym to Unicode
+//========================================================================
+
+long _glfwKeySym2Unicode( KeySym keysym )
+{
+ int min = 0;
+ int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
+ int mid;
+
+ /* First check for Latin-1 characters (1:1 mapping) */
+ if( (keysym >= 0x0020 && keysym <= 0x007e) ||
+ (keysym >= 0x00a0 && keysym <= 0x00ff) )
+ { return keysym;
+ }
+
+ /* Also check for directly encoded 24-bit UCS characters */
+ if( (keysym & 0xff000000) == 0x01000000 )
+ {
+ return keysym & 0x00ffffff;
+ }
+
+ /* Binary search in table */
+ while( max >= min )
+ {
+ mid = (min + max) / 2;
+ if( keysymtab[mid].keysym < keysym )
+ {
+ min = mid + 1;
+ }
+ else if( keysymtab[mid].keysym > keysym )
+ {
+ max = mid - 1;
+ }
+ else
+ {
+ /* Found it! */
+ return keysymtab[mid].ucs;
+ }
+ }
+
+ /* No matching Unicode value found */
+ return -1;
+}
diff --git a/lib/x11/x11_time.c b/lib/x11/x11_time.c
new file mode 100644
index 00000000..0cff709f
--- /dev/null
+++ b/lib/x11/x11_time.c
@@ -0,0 +1,89 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: X11/GLX
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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"
+
+
+//========================================================================
+// Initialise timer
+//========================================================================
+
+void _glfwInitTimer( void )
+{
+ struct timeval tv;
+
+ // "Resolution" is 1 us
+ _glfwLibrary.Timer.resolution = 1e-6;
+
+ // Set start-time for timer
+ gettimeofday( &tv, NULL );
+ _glfwLibrary.Timer.t0 = (long long) tv.tv_sec * (long long) 1000000 +
+ (long long) tv.tv_usec;
+}
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Return timer value in seconds
+//========================================================================
+
+double _glfwPlatformGetTime( void )
+{
+ long long t;
+ struct timeval tv;
+
+ gettimeofday( &tv, NULL );
+ t = (long long) tv.tv_sec * (long long) 1000000 +
+ (long long) tv.tv_usec;
+
+ return (double)(t - _glfwLibrary.Timer.t0) * _glfwLibrary.Timer.resolution;
+}
+
+
+//========================================================================
+// Set timer value in seconds
+//========================================================================
+
+void _glfwPlatformSetTime( double t )
+{
+ long long t0;
+ struct timeval tv;
+
+ gettimeofday( &tv, NULL );
+ t0 = (long long) tv.tv_sec * (long long) 1000000 +
+ (long long) tv.tv_usec;
+
+ // Calulate new starting time
+ _glfwLibrary.Timer.t0 = t0 - (long long)(t/_glfwLibrary.Timer.resolution);
+}
+
diff --git a/lib/x11/x11_window.c b/lib/x11/x11_window.c
new file mode 100644
index 00000000..e382e8ed
--- /dev/null
+++ b/lib/x11/x11_window.c
@@ -0,0 +1,1875 @@
+//========================================================================
+// GLFW - An OpenGL framework
+// Platform: X11/GLX
+// API version: 2.7
+// WWW: http://www.glfw.org/
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2010 Camilla Berglund
+//
+// 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
+
+
+/* Define GLX 1.4 FSAA tokens if not already defined */
+#ifndef GLX_VERSION_1_4
+
+#define GLX_SAMPLE_BUFFERS 100000
+#define GLX_SAMPLES 100001
+
+#endif /*GLX_VERSION_1_4*/
+
+// Action for EWMH client messages
+#define _NET_WM_STATE_REMOVE 0
+#define _NET_WM_STATE_ADD 1
+#define _NET_WM_STATE_TOGGLE 2
+
+
+//************************************************************************
+//**** GLFW internal functions ****
+//************************************************************************
+
+//========================================================================
+// Checks whether the event is a MapNotify for the specified window
+//========================================================================
+
+static Bool isMapNotify( Display *d, XEvent *e, char *arg )
+{
+ return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
+}
+
+
+//========================================================================
+// Retrieve a single window property of the specified type
+// Inspired by fghGetWindowProperty from freeglut
+//========================================================================
+
+static unsigned long getWindowProperty( Window window,
+ Atom property,
+ Atom type,
+ unsigned char** value )
+{
+ Atom actualType;
+ int actualFormat;
+ unsigned long itemCount, bytesAfter;
+
+ XGetWindowProperty( _glfwLibrary.display,
+ window,
+ property,
+ 0,
+ LONG_MAX,
+ False,
+ type,
+ &actualType,
+ &actualFormat,
+ &itemCount,
+ &bytesAfter,
+ value );
+
+ if( actualType != type )
+ {
+ return 0;
+ }
+
+ return itemCount;
+}
+
+
+//========================================================================
+// Check whether the specified atom is supported
+//========================================================================
+
+static Atom getSupportedAtom( Atom* supportedAtoms,
+ unsigned long atomCount,
+ const char* atomName )
+{
+ Atom atom = XInternAtom( _glfwLibrary.display, atomName, True );
+ if( atom != None )
+ {
+ unsigned long i;
+
+ for( i = 0; i < atomCount; i++ )
+ {
+ if( supportedAtoms[i] == atom )
+ {
+ return atom;
+ }
+ }
+ }
+
+ return None;
+}
+
+
+//========================================================================
+// Check whether the running window manager is EWMH-compliant
+//========================================================================
+
+static GLboolean checkForEWMH( void )
+{
+ Window *windowFromRoot = NULL;
+ Window *windowFromChild = NULL;
+
+ // Hey kids; let's see if the window manager supports EWMH!
+
+ // First we need a couple of atoms, which should already be there
+ Atom supportingWmCheck = XInternAtom( _glfwLibrary.display,
+ "_NET_SUPPORTING_WM_CHECK",
+ True );
+ Atom wmSupported = XInternAtom( _glfwLibrary.display,
+ "_NET_SUPPORTED",
+ True );
+ if( supportingWmCheck == None || wmSupported == None )
+ {
+ return GL_FALSE;
+ }
+
+ // Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window
+ if( getWindowProperty( _glfwWin.root,
+ supportingWmCheck,
+ XA_WINDOW,
+ (unsigned char**) &windowFromRoot ) != 1 )
+ {
+ XFree( windowFromRoot );
+ return GL_FALSE;
+ }
+
+ // It should be the ID of a child window (of the root)
+ // Then we look for the same property on the child window
+ if( getWindowProperty( *windowFromRoot,
+ supportingWmCheck,
+ XA_WINDOW,
+ (unsigned char**) &windowFromChild ) != 1 )
+ {
+ XFree( windowFromRoot );
+ XFree( windowFromChild );
+ return GL_FALSE;
+ }
+
+ // It should be the ID of that same child window
+ if( *windowFromRoot != *windowFromChild )
+ {
+ XFree( windowFromRoot );
+ XFree( windowFromChild );
+ return GL_FALSE;
+ }
+
+ XFree( windowFromRoot );
+ XFree( windowFromChild );
+
+ // We are now fairly sure that an EWMH-compliant window manager is running
+
+ Atom *supportedAtoms;
+ unsigned long atomCount;
+
+ // Now we need to check the _NET_SUPPORTED property of the root window
+ atomCount = getWindowProperty( _glfwWin.root,
+ wmSupported,
+ XA_ATOM,
+ (unsigned char**) &supportedAtoms );
+
+ // See which of the atoms we support that are supported by the WM
+
+ _glfwWin.wmState = getSupportedAtom( supportedAtoms,
+ atomCount,
+ "_NET_WM_STATE" );
+
+ _glfwWin.wmStateFullscreen = getSupportedAtom( supportedAtoms,
+ atomCount,
+ "_NET_WM_STATE_FULLSCREEN" );
+
+ _glfwWin.wmPing = getSupportedAtom( supportedAtoms,
+ atomCount,
+ "_NET_WM_PING" );
+
+ _glfwWin.wmActiveWindow = getSupportedAtom( supportedAtoms,
+ atomCount,
+ "_NET_ACTIVE_WINDOW" );
+
+ XFree( supportedAtoms );
+
+ return GL_TRUE;
+}
+
+//========================================================================
+// Translates an X Window key to internal coding
+//========================================================================
+
+static int translateKey( int keycode )
+{
+ KeySym key, key_lc, key_uc;
+
+ // Try secondary keysym, for numeric keypad keys
+ // Note: This way we always force "NumLock = ON", which at least
+ // enables GLFW users to detect numeric keypad keys
+ key = XKeycodeToKeysym( _glfwLibrary.display, keycode, 1 );
+ switch( key )
+ {
+ // Numeric keypad
+ case XK_KP_0: return GLFW_KEY_KP_0;
+ case XK_KP_1: return GLFW_KEY_KP_1;
+ case XK_KP_2: return GLFW_KEY_KP_2;
+ case XK_KP_3: return GLFW_KEY_KP_3;
+ case XK_KP_4: return GLFW_KEY_KP_4;
+ case XK_KP_5: return GLFW_KEY_KP_5;
+ case XK_KP_6: return GLFW_KEY_KP_6;
+ case XK_KP_7: return GLFW_KEY_KP_7;
+ case XK_KP_8: return GLFW_KEY_KP_8;
+ case XK_KP_9: return GLFW_KEY_KP_9;
+ case XK_KP_Separator:
+ case XK_KP_Decimal: return GLFW_KEY_KP_DECIMAL;
+ case XK_KP_Equal: return GLFW_KEY_KP_EQUAL;
+ case XK_KP_Enter: return GLFW_KEY_KP_ENTER;
+ default: break;
+ }
+
+ // Now try pimary keysym
+ key = XKeycodeToKeysym( _glfwLibrary.display, keycode, 0 );
+ switch( key )
+ {
+ // Special keys (non character keys)
+ case XK_Escape: return GLFW_KEY_ESC;
+ case XK_Tab: return GLFW_KEY_TAB;
+ case XK_Shift_L: return GLFW_KEY_LSHIFT;
+ case XK_Shift_R: return GLFW_KEY_RSHIFT;
+ case XK_Control_L: return GLFW_KEY_LCTRL;
+ case XK_Control_R: return GLFW_KEY_RCTRL;
+ case XK_Meta_L:
+ case XK_Alt_L: return GLFW_KEY_LALT;
+ case XK_Mode_switch: // Mapped to Alt_R on many keyboards
+ case XK_Meta_R:
+ case XK_ISO_Level3_Shift: // AltGr on at least some machines
+ case XK_Alt_R: return GLFW_KEY_RALT;
+ case XK_Super_L: return GLFW_KEY_LSUPER;
+ case XK_Super_R: return GLFW_KEY_RSUPER;
+ case XK_Menu: return GLFW_KEY_MENU;
+ case XK_Num_Lock: return GLFW_KEY_KP_NUM_LOCK;
+ case XK_Caps_Lock: return GLFW_KEY_CAPS_LOCK;
+ case XK_Scroll_Lock: return GLFW_KEY_SCROLL_LOCK;
+ case XK_Pause: return GLFW_KEY_PAUSE;
+ case XK_KP_Delete:
+ case XK_Delete: return GLFW_KEY_DEL;
+ case XK_BackSpace: return GLFW_KEY_BACKSPACE;
+ case XK_Return: return GLFW_KEY_ENTER;
+ case XK_KP_Home:
+ case XK_Home: return GLFW_KEY_HOME;
+ case XK_KP_End:
+ case XK_End: return GLFW_KEY_END;
+ case XK_KP_Page_Up:
+ case XK_Page_Up: return GLFW_KEY_PAGEUP;
+ case XK_KP_Page_Down:
+ case XK_Page_Down: return GLFW_KEY_PAGEDOWN;
+ case XK_KP_Insert:
+ case XK_Insert: return GLFW_KEY_INSERT;
+ case XK_KP_Left:
+ case XK_Left: return GLFW_KEY_LEFT;
+ case XK_KP_Right:
+ case XK_Right: return GLFW_KEY_RIGHT;
+ case XK_KP_Down:
+ case XK_Down: return GLFW_KEY_DOWN;
+ case XK_KP_Up:
+ case XK_Up: return GLFW_KEY_UP;
+ case XK_F1: return GLFW_KEY_F1;
+ case XK_F2: return GLFW_KEY_F2;
+ case XK_F3: return GLFW_KEY_F3;
+ case XK_F4: return GLFW_KEY_F4;
+ case XK_F5: return GLFW_KEY_F5;
+ case XK_F6: return GLFW_KEY_F6;
+ case XK_F7: return GLFW_KEY_F7;
+ case XK_F8: return GLFW_KEY_F8;
+ case XK_F9: return GLFW_KEY_F9;
+ case XK_F10: return GLFW_KEY_F10;
+ case XK_F11: return GLFW_KEY_F11;
+ case XK_F12: return GLFW_KEY_F12;
+ case XK_F13: return GLFW_KEY_F13;
+ case XK_F14: return GLFW_KEY_F14;
+ case XK_F15: return GLFW_KEY_F15;
+ case XK_F16: return GLFW_KEY_F16;
+ case XK_F17: return GLFW_KEY_F17;
+ case XK_F18: return GLFW_KEY_F18;
+ case XK_F19: return GLFW_KEY_F19;
+ case XK_F20: return GLFW_KEY_F20;
+ case XK_F21: return GLFW_KEY_F21;
+ case XK_F22: return GLFW_KEY_F22;
+ case XK_F23: return GLFW_KEY_F23;
+ case XK_F24: return GLFW_KEY_F24;
+ case XK_F25: return GLFW_KEY_F25;
+
+ // Numeric keypad (should have been detected in secondary keysym!)
+ case XK_KP_Divide: return GLFW_KEY_KP_DIVIDE;
+ case XK_KP_Multiply: return GLFW_KEY_KP_MULTIPLY;
+ case XK_KP_Subtract: return GLFW_KEY_KP_SUBTRACT;
+ case XK_KP_Add: return GLFW_KEY_KP_ADD;
+ case XK_KP_Equal: return GLFW_KEY_KP_EQUAL;
+ case XK_KP_Enter: return GLFW_KEY_KP_ENTER;
+
+ // The rest (should be printable keys)
+ default:
+ // Make uppercase
+ XConvertCase( key, &key_lc, &key_uc );
+ key = key_uc;
+
+ // Valid ISO 8859-1 character?
+ if( (key >= 32 && key <= 126) ||
+ (key >= 160 && key <= 255) )
+ {
+ return (int) key;
+ }
+ return GLFW_KEY_UNKNOWN;
+ }
+}
+
+
+//========================================================================
+// Translates an X Window event to Unicode
+//========================================================================
+
+static int translateChar( XKeyEvent *event )
+{
+ KeySym keysym;
+
+ // Get X11 keysym
+ XLookupString( event, NULL, 0, &keysym, NULL );
+
+ // Convert to Unicode (see x11_keysym2unicode.c)
+ return (int) _glfwKeySym2Unicode( keysym );
+}
+
+
+//========================================================================
+// Create a blank cursor (for locked mouse mode)
+//========================================================================
+
+static Cursor createNULLCursor( Display *display, Window root )
+{
+ Pixmap cursormask;
+ XGCValues xgc;
+ GC gc;
+ XColor col;
+ Cursor cursor;
+
+ cursormask = XCreatePixmap( display, root, 1, 1, 1 );
+ xgc.function = GXclear;
+ gc = XCreateGC( display, cursormask, GCFunction, &xgc );
+ XFillRectangle( display, cursormask, gc, 0, 0, 1, 1 );
+ col.pixel = 0;
+ col.red = 0;
+ col.flags = 4;
+ cursor = XCreatePixmapCursor( display, cursormask, cursormask,
+ &col,&col, 0,0 );
+ XFreePixmap( display, cursormask );
+ XFreeGC( display, gc );
+
+ return cursor;
+}
+
+
+//========================================================================
+// Returns the specified attribute of the specified GLXFBConfig
+// NOTE: Do not call this unless we have found GLX 1.3+ or GLX_SGIX_fbconfig
+//========================================================================
+
+static int getFBConfigAttrib( GLXFBConfig fbconfig, int attrib )
+{
+ int value;
+
+ if( _glfwWin.has_GLX_SGIX_fbconfig )
+ {
+ _glfwWin.GetFBConfigAttribSGIX( _glfwLibrary.display, fbconfig, attrib, &value );
+ }
+ else
+ {
+ glXGetFBConfigAttrib( _glfwLibrary.display, fbconfig, attrib, &value );
+ }
+
+ return value;
+}
+
+
+//========================================================================
+// Return a list of available and usable framebuffer configs
+//========================================================================
+
+static _GLFWfbconfig *getFBConfigs( unsigned int *found )
+{
+ GLXFBConfig *fbconfigs;
+ _GLFWfbconfig *result;
+ int i, count = 0;
+
+ *found = 0;
+
+ if( _glfwLibrary.glxMajor == 1 && _glfwLibrary.glxMinor < 3 )
+ {
+ if( !_glfwWin.has_GLX_SGIX_fbconfig )
+ {
+ fprintf( stderr, "GLXFBConfigs are not supported by the X server\n" );
+ return NULL;
+ }
+ }
+
+ if( _glfwWin.has_GLX_SGIX_fbconfig )
+ {
+ fbconfigs = _glfwWin.ChooseFBConfigSGIX( _glfwLibrary.display,
+ _glfwWin.screen,
+ NULL,
+ &count );
+ if( !count )
+ {
+ fprintf( stderr, "No GLXFBConfigs returned\n" );
+ return NULL;
+ }
+ }
+ else
+ {
+ fbconfigs = glXGetFBConfigs( _glfwLibrary.display, _glfwWin.screen, &count );
+ if( !count )
+ {
+ fprintf( stderr, "No GLXFBConfigs returned\n" );
+ return NULL;
+ }
+ }
+
+ result = (_GLFWfbconfig*) malloc( sizeof(_GLFWfbconfig) * count );
+ if( !result )
+ {
+ fprintf( stderr, "Out of memory\n" );
+ return NULL;
+ }
+
+ for( i = 0; i < count; i++ )
+ {
+ if( !getFBConfigAttrib( fbconfigs[i], GLX_DOUBLEBUFFER ) ||
+ !getFBConfigAttrib( fbconfigs[i], GLX_VISUAL_ID ) )
+ {
+ // Only consider double-buffered GLXFBConfigs with associated visuals
+ continue;
+ }
+
+ if( !( getFBConfigAttrib( fbconfigs[i], GLX_RENDER_TYPE ) & GLX_RGBA_BIT ) )
+ {
+ // Only consider RGBA GLXFBConfigs
+ continue;
+ }
+
+ if( !( getFBConfigAttrib( fbconfigs[i], GLX_DRAWABLE_TYPE ) & GLX_WINDOW_BIT ) )
+ {
+ // Only consider window GLXFBConfigs
+ continue;
+ }
+
+ result[*found].redBits = getFBConfigAttrib( fbconfigs[i], GLX_RED_SIZE );
+ result[*found].greenBits = getFBConfigAttrib( fbconfigs[i], GLX_GREEN_SIZE );
+ result[*found].blueBits = getFBConfigAttrib( fbconfigs[i], GLX_BLUE_SIZE );
+
+ result[*found].alphaBits = getFBConfigAttrib( fbconfigs[i], GLX_ALPHA_SIZE );
+ result[*found].depthBits = getFBConfigAttrib( fbconfigs[i], GLX_DEPTH_SIZE );
+ result[*found].stencilBits = getFBConfigAttrib( fbconfigs[i], GLX_STENCIL_SIZE );
+
+ result[*found].accumRedBits = getFBConfigAttrib( fbconfigs[i], GLX_ACCUM_RED_SIZE );
+ result[*found].accumGreenBits = getFBConfigAttrib( fbconfigs[i], GLX_ACCUM_GREEN_SIZE );
+ result[*found].accumBlueBits = getFBConfigAttrib( fbconfigs[i], GLX_ACCUM_BLUE_SIZE );
+ result[*found].accumAlphaBits = getFBConfigAttrib( fbconfigs[i], GLX_ACCUM_ALPHA_SIZE );
+
+ result[*found].auxBuffers = getFBConfigAttrib( fbconfigs[i], GLX_AUX_BUFFERS );
+ result[*found].stereo = getFBConfigAttrib( fbconfigs[i], GLX_STEREO );
+
+ if( _glfwWin.has_GLX_ARB_multisample )
+ {
+ result[*found].samples = getFBConfigAttrib( fbconfigs[i], GLX_SAMPLES );
+ }
+ else
+ {
+ result[*found].samples = 0;
+ }
+
+ result[*found].platformID = (GLFWintptr) getFBConfigAttrib( fbconfigs[i], GLX_FBCONFIG_ID );
+
+ (*found)++;
+ }
+
+ XFree( fbconfigs );
+
+ return result;
+}
+
+
+//========================================================================
+// Create the OpenGL context
+//========================================================================
+
+#define setGLXattrib( attribs, index, attribName, attribValue ) \
+ attribs[index++] = attribName; \
+ attribs[index++] = attribValue;
+
+static int createContext( const _GLFWwndconfig *wndconfig, GLXFBConfigID fbconfigID )
+{
+ int attribs[40];
+ int flags, dummy, index;
+ GLXFBConfig *fbconfig;
+
+ // Retrieve the previously selected GLXFBConfig
+ {
+ index = 0;
+
+ setGLXattrib( attribs, index, GLX_FBCONFIG_ID, (int) fbconfigID );
+ setGLXattrib( attribs, index, None, None );
+
+ if( _glfwWin.has_GLX_SGIX_fbconfig )
+ {
+ fbconfig = _glfwWin.ChooseFBConfigSGIX( _glfwLibrary.display,
+ _glfwWin.screen,
+ attribs,
+ &dummy );
+ }
+ else
+ {
+ fbconfig = glXChooseFBConfig( _glfwLibrary.display,
+ _glfwWin.screen,
+ attribs,
+ &dummy );
+ }
+
+ if( fbconfig == NULL )
+ {
+ fprintf(stderr, "Unable to retrieve the selected GLXFBConfig\n");
+ return GL_FALSE;
+ }
+ }
+
+ // Retrieve the corresponding visual
+ if( _glfwWin.has_GLX_SGIX_fbconfig )
+ {
+ _glfwWin.visual = _glfwWin.GetVisualFromFBConfigSGIX( _glfwLibrary.display,
+ *fbconfig );
+ }
+ else
+ {
+ _glfwWin.visual = glXGetVisualFromFBConfig( _glfwLibrary.display, *fbconfig );
+ }
+
+ if( _glfwWin.visual == NULL )
+ {
+ XFree( fbconfig );
+
+ fprintf(stderr, "Unable to retrieve visual for GLXFBconfig\n");
+ return GL_FALSE;
+ }
+
+ if( _glfwWin.has_GLX_ARB_create_context )
+ {
+ index = 0;
+
+ if( wndconfig->glMajor != 1 || wndconfig->glMinor != 0 )
+ {
+ // Request an explicitly versioned context
+
+ setGLXattrib( attribs, index, GLX_CONTEXT_MAJOR_VERSION_ARB, wndconfig->glMajor );
+ setGLXattrib( attribs, index, GLX_CONTEXT_MINOR_VERSION_ARB, wndconfig->glMinor );
+ }
+
+ if( wndconfig->glForward || wndconfig->glDebug )
+ {
+ flags = 0;
+
+ if( wndconfig->glForward )
+ {
+ flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
+ }
+
+ if( wndconfig->glDebug )
+ {
+ flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
+ }
+
+ setGLXattrib( attribs, index, GLX_CONTEXT_FLAGS_ARB, flags );
+ }
+
+ if( wndconfig->glProfile )
+ {
+ if( !_glfwWin.has_GLX_ARB_create_context_profile )
+ {
+ fprintf( stderr, "OpenGL profile requested but GLX_ARB_create_context_profile "
+ "is unavailable\n" );
+ return GL_FALSE;
+ }
+
+ if( wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE )
+ {
+ flags = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+ }
+ else
+ {
+ flags = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
+ }
+
+ setGLXattrib( attribs, index, GLX_CONTEXT_PROFILE_MASK_ARB, flags );
+ }
+
+ setGLXattrib( attribs, index, None, None );
+
+ _glfwWin.context = _glfwWin.CreateContextAttribsARB( _glfwLibrary.display,
+ *fbconfig,
+ NULL,
+ True,
+ attribs );
+ }
+ else
+ {
+ if( _glfwWin.has_GLX_SGIX_fbconfig )
+ {
+ _glfwWin.context = _glfwWin.CreateContextWithConfigSGIX( _glfwLibrary.display,
+ *fbconfig,
+ GLX_RGBA_TYPE,
+ NULL,
+ True );
+ }
+ else
+ {
+ _glfwWin.context = glXCreateNewContext( _glfwLibrary.display,
+ *fbconfig,
+ GLX_RGBA_TYPE,
+ NULL,
+ True );
+ }
+ }
+
+ XFree( fbconfig );
+
+ if( _glfwWin.context == NULL )
+ {
+ fprintf(stderr, "Unable to create OpenGL context\n");
+ return GL_FALSE;
+ }
+
+ _glfwWin.fbconfigID = fbconfigID;
+
+ return GL_TRUE;
+}
+
+#undef setGLXattrib
+
+
+//========================================================================
+// Initialize GLX-specific extensions
+//========================================================================
+
+static void initGLXExtensions( void )
+{
+ // This needs to include every function pointer loaded below
+ _glfwWin.SwapIntervalSGI = NULL;
+ _glfwWin.GetFBConfigAttribSGIX = NULL;
+ _glfwWin.ChooseFBConfigSGIX = NULL;
+ _glfwWin.CreateContextWithConfigSGIX = NULL;
+ _glfwWin.GetVisualFromFBConfigSGIX = NULL;
+ _glfwWin.CreateContextAttribsARB = NULL;
+
+ // This needs to include every extension used below
+ _glfwWin.has_GLX_SGIX_fbconfig = GL_FALSE;
+ _glfwWin.has_GLX_SGI_swap_control = GL_FALSE;
+ _glfwWin.has_GLX_ARB_multisample = GL_FALSE;
+ _glfwWin.has_GLX_ARB_create_context = GL_FALSE;
+ _glfwWin.has_GLX_ARB_create_context_profile = GL_FALSE;
+
+ if( _glfwPlatformExtensionSupported( "GLX_SGI_swap_control" ) )
+ {
+ _glfwWin.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
+ _glfwPlatformGetProcAddress( "glXSwapIntervalSGI" );
+
+ if( _glfwWin.SwapIntervalSGI )
+ {
+ _glfwWin.has_GLX_SGI_swap_control = GL_TRUE;
+ }
+ }
+
+ if( _glfwPlatformExtensionSupported( "GLX_SGIX_fbconfig" ) )
+ {
+ _glfwWin.GetFBConfigAttribSGIX = (PFNGLXGETFBCONFIGATTRIBSGIXPROC)
+ _glfwPlatformGetProcAddress( "glXGetFBConfigAttribSGIX" );
+ _glfwWin.ChooseFBConfigSGIX = (PFNGLXCHOOSEFBCONFIGSGIXPROC)
+ _glfwPlatformGetProcAddress( "glXChooseFBConfigSGIX" );
+ _glfwWin.CreateContextWithConfigSGIX = (PFNGLXCREATECONTEXTWITHCONFIGSGIXPROC)
+ _glfwPlatformGetProcAddress( "glXCreateContextWithConfigSGIX" );
+ _glfwWin.GetVisualFromFBConfigSGIX = (PFNGLXGETVISUALFROMFBCONFIGSGIXPROC)
+ _glfwPlatformGetProcAddress( "glXGetVisualFromFBConfigSGIX" );
+
+ if( _glfwWin.GetFBConfigAttribSGIX &&
+ _glfwWin.ChooseFBConfigSGIX &&
+ _glfwWin.CreateContextWithConfigSGIX &&
+ _glfwWin.GetVisualFromFBConfigSGIX )
+ {
+ _glfwWin.has_GLX_SGIX_fbconfig = GL_TRUE;
+ }
+ }
+
+ if( _glfwPlatformExtensionSupported( "GLX_ARB_multisample" ) )
+ {
+ _glfwWin.has_GLX_ARB_multisample = GL_TRUE;
+ }
+
+ if( _glfwPlatformExtensionSupported( "GLX_ARB_create_context" ) )
+ {
+ _glfwWin.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
+ _glfwPlatformGetProcAddress( "glXCreateContextAttribsARB" );
+
+ if( _glfwWin.CreateContextAttribsARB )
+ {
+ _glfwWin.has_GLX_ARB_create_context = GL_TRUE;
+ }
+ }
+
+ if( _glfwPlatformExtensionSupported( "GLX_ARB_create_context_profile" ) )
+ {
+ _glfwWin.has_GLX_ARB_create_context_profile = GL_TRUE;
+ }
+}
+
+
+//========================================================================
+// Create the X11 window (and its colormap)
+//========================================================================
+
+static GLboolean createWindow( int width, int height,
+ const _GLFWwndconfig *wndconfig )
+{
+ XEvent event;
+ unsigned long wamask;
+ XSetWindowAttributes wa;
+
+ // Every window needs a colormap
+ // Create one based on the visual used by the current context
+
+ _glfwWin.colormap = XCreateColormap( _glfwLibrary.display,
+ _glfwWin.root,
+ _glfwWin.visual->visual,
+ AllocNone );
+
+ // Create the actual window
+ {
+ wamask = CWBorderPixel | CWColormap | CWEventMask;
+
+ wa.colormap = _glfwWin.colormap;
+ wa.border_pixel = 0;
+ wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
+ PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
+ ExposureMask | FocusChangeMask | VisibilityChangeMask;
+
+ if( wndconfig->mode == GLFW_WINDOW )
+ {
+ // The /only/ reason we are setting the background pixel here is
+ // that otherwise our window wont get any decorations on systems
+ // using Compiz on Intel hardware
+ wa.background_pixel = BlackPixel( _glfwLibrary.display, _glfwWin.screen );
+ wamask |= CWBackPixel;
+ }
+
+ _glfwWin.window = XCreateWindow(
+ _glfwLibrary.display,
+ _glfwWin.root,
+ 0, 0, // Upper left corner of this window on root
+ _glfwWin.width, _glfwWin.height,
+ 0, // Border width
+ _glfwWin.visual->depth, // Color depth
+ InputOutput,
+ _glfwWin.visual->visual,
+ wamask,
+ &wa
+ );
+ if( !_glfwWin.window )
+ {
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+ }
+
+ // Check whether an EWMH-compliant window manager is running
+ _glfwWin.hasEWMH = checkForEWMH();
+
+ if( _glfwWin.fullscreen && !_glfwWin.hasEWMH )
+ {
+ // This is the butcher's way of removing window decorations
+ // Setting the override-redirect attribute on a window makes the window
+ // manager ignore the window completely (ICCCM, section 4)
+ // The good thing is that this makes undecorated fullscreen windows
+ // easy to do; the bad thing is that we have to do everything manually
+ // and some things (like iconify/restore) won't work at all, as they're
+ // usually performed by the window manager
+
+ XSetWindowAttributes attributes;
+ attributes.override_redirect = True;
+ XChangeWindowAttributes( _glfwLibrary.display,
+ _glfwWin.window,
+ CWOverrideRedirect,
+ &attributes );
+
+ _glfwWin.overrideRedirect = GL_TRUE;
+ }
+
+ // Find or create the protocol atom for window close notifications
+ _glfwWin.wmDeleteWindow = XInternAtom( _glfwLibrary.display,
+ "WM_DELETE_WINDOW",
+ False );
+
+ // Declare the WM protocols we support
+ {
+ int count = 0;
+ Atom protocols[2];
+
+ // The WM_DELETE_WINDOW ICCCM protocol
+ // Basic window close notification protocol
+ if( _glfwWin.wmDeleteWindow != None )
+ {
+ protocols[count++] = _glfwWin.wmDeleteWindow;
+ }
+
+ // The _NET_WM_PING EWMH protocol
+ // Tells the WM to ping our window and flag us as unresponsive if we
+ // don't reply within a few seconds
+ if( _glfwWin.wmPing != None )
+ {
+ protocols[count++] = _glfwWin.wmPing;
+ }
+
+ if( count > 0 )
+ {
+ XSetWMProtocols( _glfwLibrary.display, _glfwWin.window,
+ protocols, count );
+ }
+ }
+
+ // Set ICCCM WM_HINTS property
+ {
+ XWMHints *hints = XAllocWMHints();
+ if( !hints )
+ {
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ hints->flags = StateHint;
+ hints->initial_state = NormalState;
+
+ XSetWMHints( _glfwLibrary.display, _glfwWin.window, hints );
+ XFree( hints );
+ }
+
+ // Set ICCCM WM_NORMAL_HINTS property (even if no parts are set)
+ {
+ XSizeHints *hints = XAllocSizeHints();
+ if( !hints )
+ {
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ hints->flags = 0;
+
+ if( wndconfig->windowNoResize )
+ {
+ hints->flags |= (PMinSize | PMaxSize);
+ hints->min_width = hints->max_width = _glfwWin.width;
+ hints->min_height = hints->max_height = _glfwWin.height;
+ }
+
+ XSetWMNormalHints( _glfwLibrary.display, _glfwWin.window, hints );
+ XFree( hints );
+ }
+
+ _glfwPlatformSetWindowTitle( "GLFW Window" );
+
+ // Make sure the window is mapped before proceeding
+ XMapWindow( _glfwLibrary.display, _glfwWin.window );
+ XPeekIfEvent( _glfwLibrary.display, &event, isMapNotify,
+ (char*)_glfwWin.window );
+
+ return GL_TRUE;
+}
+
+
+//========================================================================
+// Enter fullscreen mode
+//========================================================================
+
+static void enterFullscreenMode( void )
+{
+ if( !_glfwWin.Saver.changed )
+ {
+ // Remember old screen saver settings
+ XGetScreenSaver( _glfwLibrary.display,
+ &_glfwWin.Saver.timeout, &_glfwWin.Saver.interval,
+ &_glfwWin.Saver.blanking, &_glfwWin.Saver.exposure );
+
+ // Disable screen saver
+ XSetScreenSaver( _glfwLibrary.display, 0, 0, DontPreferBlanking,
+ DefaultExposures );
+
+ _glfwWin.Saver.changed = GL_TRUE;
+ }
+
+ _glfwSetVideoMode( _glfwWin.screen,
+ &_glfwWin.width, &_glfwWin.height,
+ &_glfwWin.refreshRate );
+
+ if( _glfwWin.hasEWMH &&
+ _glfwWin.wmState != None &&
+ _glfwWin.wmStateFullscreen != None )
+ {
+ if( _glfwWin.wmActiveWindow != None )
+ {
+ // Ask the window manager to raise and focus the GLFW window
+ // Only focused windows with the _NET_WM_STATE_FULLSCREEN state end
+ // up on top of all other windows ("Stacking order" in EWMH spec)
+
+ XEvent event;
+ memset( &event, 0, sizeof(event) );
+
+ event.type = ClientMessage;
+ event.xclient.window = _glfwWin.window;
+ event.xclient.format = 32; // Data is 32-bit longs
+ event.xclient.message_type = _glfwWin.wmActiveWindow;
+ event.xclient.data.l[0] = 1; // Sender is a normal application
+ event.xclient.data.l[1] = 0; // We don't really know the timestamp
+
+ XSendEvent( _glfwLibrary.display,
+ _glfwWin.root,
+ False,
+ SubstructureNotifyMask | SubstructureRedirectMask,
+ &event );
+ }
+
+ // Ask the window manager to make the GLFW window a fullscreen window
+ // Fullscreen windows are undecorated and, when focused, are kept
+ // on top of all other windows
+
+ XEvent event;
+ memset( &event, 0, sizeof(event) );
+
+ event.type = ClientMessage;
+ event.xclient.window = _glfwWin.window;
+ event.xclient.format = 32; // Data is 32-bit longs
+ event.xclient.message_type = _glfwWin.wmState;
+ event.xclient.data.l[0] = _NET_WM_STATE_ADD;
+ event.xclient.data.l[1] = _glfwWin.wmStateFullscreen;
+ event.xclient.data.l[2] = 0; // No secondary property
+ event.xclient.data.l[3] = 1; // Sender is a normal application
+
+ XSendEvent( _glfwLibrary.display,
+ _glfwWin.root,
+ False,
+ SubstructureNotifyMask | SubstructureRedirectMask,
+ &event );
+ }
+ else if( _glfwWin.overrideRedirect )
+ {
+ // In override-redirect mode, we have divorced ourselves from the
+ // window manager, so we need to do everything manually
+
+ XRaiseWindow( _glfwLibrary.display, _glfwWin.window );
+ XSetInputFocus( _glfwLibrary.display, _glfwWin.window,
+ RevertToParent, CurrentTime );
+ XMoveWindow( _glfwLibrary.display, _glfwWin.window, 0, 0 );
+ XResizeWindow( _glfwLibrary.display, _glfwWin.window,
+ _glfwWin.width, _glfwWin.height );
+ }
+
+ if( _glfwWin.mouseLock )
+ {
+ _glfwPlatformHideMouseCursor();
+ }
+
+ // HACK: Try to get window inside viewport (for virtual displays) by moving
+ // the mouse cursor to the upper left corner (and then to the center)
+ // This hack should be harmless on saner systems as well
+ XWarpPointer( _glfwLibrary.display, None, _glfwWin.window, 0,0,0,0, 0,0 );
+ XWarpPointer( _glfwLibrary.display, None, _glfwWin.window, 0,0,0,0,
+ _glfwWin.width / 2, _glfwWin.height / 2 );
+}
+
+//========================================================================
+// Leave fullscreen mode
+//========================================================================
+
+static void leaveFullscreenMode( void )
+{
+ _glfwRestoreVideoMode();
+
+ // Did we change the screen saver setting?
+ if( _glfwWin.Saver.changed )
+ {
+ // Restore old screen saver settings
+ XSetScreenSaver( _glfwLibrary.display,
+ _glfwWin.Saver.timeout,
+ _glfwWin.Saver.interval,
+ _glfwWin.Saver.blanking,
+ _glfwWin.Saver.exposure );
+
+ _glfwWin.Saver.changed = GL_FALSE;
+ }
+
+ if( _glfwWin.hasEWMH &&
+ _glfwWin.wmState != None &&
+ _glfwWin.wmStateFullscreen != None )
+ {
+ // Ask the window manager to make the GLFW window a normal window
+ // Normal windows usually have frames and other decorations
+
+ XEvent event;
+ memset( &event, 0, sizeof(event) );
+
+ event.type = ClientMessage;
+ event.xclient.window = _glfwWin.window;
+ event.xclient.format = 32; // Data is 32-bit longs
+ event.xclient.message_type = _glfwWin.wmState;
+ event.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
+ event.xclient.data.l[1] = _glfwWin.wmStateFullscreen;
+ event.xclient.data.l[2] = 0; // No secondary property
+ event.xclient.data.l[3] = 1; // Sender is a normal application
+
+ XSendEvent( _glfwLibrary.display,
+ _glfwWin.root,
+ False,
+ SubstructureNotifyMask | SubstructureRedirectMask,
+ &event );
+ }
+
+ if( _glfwWin.mouseLock )
+ {
+ _glfwPlatformShowMouseCursor();
+ }
+}
+
+//========================================================================
+// Get and process next X event (called by _glfwPlatformPollEvents)
+// Returns GL_TRUE if a window close request was received
+//========================================================================
+
+static GLboolean processSingleEvent( void )
+{
+ XEvent event;
+ XNextEvent( _glfwLibrary.display, &event );
+
+ switch( event.type )
+ {
+ case KeyPress:
+ {
+ // A keyboard key was pressed
+
+ // Translate and report key press
+ _glfwInputKey( translateKey( event.xkey.keycode ), GLFW_PRESS );
+
+ // Translate and report character input
+ if( _glfwWin.charCallback )
+ {
+ _glfwInputChar( translateChar( &event.xkey ), GLFW_PRESS );
+ }
+ break;
+ }
+
+ case KeyRelease:
+ {
+ // A keyboard key was released
+
+ // Do not report key releases for key repeats. For key repeats we
+ // will get KeyRelease/KeyPress pairs with similar or identical
+ // time stamps. User selected key repeat filtering is handled in
+ // _glfwInputKey()/_glfwInputChar().
+ if( XEventsQueued( _glfwLibrary.display, QueuedAfterReading ) )
+ {
+ XEvent nextEvent;
+ XPeekEvent( _glfwLibrary.display, &nextEvent );
+
+ if( nextEvent.type == KeyPress &&
+ nextEvent.xkey.window == event.xkey.window &&
+ nextEvent.xkey.keycode == event.xkey.keycode )
+ {
+ // This last check is a hack to work around key repeats
+ // leaking through due to some sort of time drift
+ // Toshiyuki Takahashi can press a button 16 times per
+ // second so it's fairly safe to assume that no human is
+ // pressing the key 50 times per second (value is ms)
+ if( ( nextEvent.xkey.time - event.xkey.time ) < 20 )
+ {
+ // Do not report anything for this event
+ break;
+ }
+ }
+ }
+
+ // Translate and report key release
+ _glfwInputKey( translateKey( event.xkey.keycode ), GLFW_RELEASE );
+
+ // Translate and report character input
+ if( _glfwWin.charCallback )
+ {
+ _glfwInputChar( translateChar( &event.xkey ), GLFW_RELEASE );
+ }
+ break;
+ }
+
+ case ButtonPress:
+ {
+ // A mouse button was pressed or a scrolling event occurred
+
+ if( event.xbutton.button == Button1 )
+ {
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS );
+ }
+ else if( event.xbutton.button == Button2 )
+ {
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS );
+ }
+ else if( event.xbutton.button == Button3 )
+ {
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS );
+ }
+
+ // XFree86 3.3.2 and later translates mouse wheel up/down into
+ // mouse button 4 & 5 presses
+ else if( event.xbutton.button == Button4 )
+ {
+ _glfwInput.WheelPos++; // To verify: is this up or down?
+ if( _glfwWin.mouseWheelCallback )
+ {
+ _glfwWin.mouseWheelCallback( _glfwInput.WheelPos );
+ }
+ }
+ else if( event.xbutton.button == Button5 )
+ {
+ _glfwInput.WheelPos--;
+ if( _glfwWin.mouseWheelCallback )
+ {
+ _glfwWin.mouseWheelCallback( _glfwInput.WheelPos );
+ }
+ }
+ break;
+ }
+
+ case ButtonRelease:
+ {
+ // A mouse button was released
+
+ if( event.xbutton.button == Button1 )
+ {
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_LEFT,
+ GLFW_RELEASE );
+ }
+ else if( event.xbutton.button == Button2 )
+ {
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_MIDDLE,
+ GLFW_RELEASE );
+ }
+ else if( event.xbutton.button == Button3 )
+ {
+ _glfwInputMouseClick( GLFW_MOUSE_BUTTON_RIGHT,
+ GLFW_RELEASE );
+ }
+ break;
+ }
+
+ case MotionNotify:
+ {
+ // The mouse cursor was moved
+
+ if( event.xmotion.x != _glfwInput.CursorPosX ||
+ event.xmotion.y != _glfwInput.CursorPosY )
+ {
+ // The mouse cursor was moved and we didn't do it
+
+ if( _glfwWin.mouseLock )
+ {
+ if( _glfwWin.pointerHidden )
+ {
+ _glfwInput.MousePosX += event.xmotion.x -
+ _glfwInput.CursorPosX;
+ _glfwInput.MousePosY += event.xmotion.y -
+ _glfwInput.CursorPosY;
+ }
+ }
+ else
+ {
+ _glfwInput.MousePosX = event.xmotion.x;
+ _glfwInput.MousePosY = event.xmotion.y;
+ }
+
+ _glfwInput.CursorPosX = event.xmotion.x;
+ _glfwInput.CursorPosY = event.xmotion.y;
+ _glfwInput.MouseMoved = GL_TRUE;
+
+ if( _glfwWin.mousePosCallback )
+ {
+ _glfwWin.mousePosCallback( _glfwInput.MousePosX,
+ _glfwInput.MousePosY );
+ }
+ }
+ break;
+ }
+
+ case ConfigureNotify:
+ {
+ if( event.xconfigure.width != _glfwWin.width ||
+ event.xconfigure.height != _glfwWin.height )
+ {
+ // The window was resized
+
+ _glfwWin.width = event.xconfigure.width;
+ _glfwWin.height = event.xconfigure.height;
+ if( _glfwWin.windowSizeCallback )
+ {
+ _glfwWin.windowSizeCallback( _glfwWin.width,
+ _glfwWin.height );
+ }
+ }
+ break;
+ }
+
+ case ClientMessage:
+ {
+ if( (Atom) event.xclient.data.l[ 0 ] == _glfwWin.wmDeleteWindow )
+ {
+ // The window manager was asked to close the window, for example by
+ // the user pressing a 'close' window decoration button
+
+ return GL_TRUE;
+ }
+ else if( _glfwWin.wmPing != None &&
+ (Atom) event.xclient.data.l[ 0 ] == _glfwWin.wmPing )
+ {
+ // The window manager is pinging us to make sure we are still
+ // responding to events
+
+ event.xclient.window = _glfwWin.root;
+ XSendEvent( _glfwLibrary.display,
+ event.xclient.window,
+ False,
+ SubstructureNotifyMask | SubstructureRedirectMask,
+ &event );
+ }
+
+ break;
+ }
+
+ case MapNotify:
+ {
+ // The window was mapped
+
+ _glfwWin.iconified = GL_FALSE;
+ break;
+ }
+
+ case UnmapNotify:
+ {
+ // The window was unmapped
+
+ _glfwWin.iconified = GL_TRUE;
+ break;
+ }
+
+ case FocusIn:
+ {
+ // The window gained focus
+
+ _glfwWin.active = GL_TRUE;
+
+ if( _glfwWin.mouseLock )
+ {
+ _glfwPlatformHideMouseCursor();
+ }
+
+ break;
+ }
+
+ case FocusOut:
+ {
+ // The window lost focus
+
+ _glfwWin.active = GL_FALSE;
+ _glfwInputDeactivation();
+
+ if( _glfwWin.mouseLock )
+ {
+ _glfwPlatformShowMouseCursor();
+ }
+
+ break;
+ }
+
+ case Expose:
+ {
+ // The window's contents was damaged
+
+ if( _glfwWin.windowRefreshCallback )
+ {
+ _glfwWin.windowRefreshCallback();
+ }
+ break;
+ }
+
+ // Was the window destroyed?
+ case DestroyNotify:
+ return GL_FALSE;
+
+ default:
+ {
+#if defined( _GLFW_HAS_XRANDR )
+ switch( event.type - _glfwLibrary.XRandR.eventBase )
+ {
+ case RRScreenChangeNotify:
+ {
+ // Show XRandR that we really care
+ XRRUpdateConfiguration( &event );
+ break;
+ }
+ }
+#endif
+ break;
+ }
+ }
+
+ // The window was not destroyed
+ return GL_FALSE;
+}
+
+
+
+//************************************************************************
+//**** Platform implementation functions ****
+//************************************************************************
+
+//========================================================================
+// Here is where the window is created, and
+// the OpenGL rendering context is created
+//========================================================================
+
+int _glfwPlatformOpenWindow( int width, int height,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWfbconfig* fbconfig )
+{
+ _GLFWfbconfig closest;
+
+ // Clear platform specific GLFW window state
+ _glfwWin.visual = (XVisualInfo*)NULL;
+ _glfwWin.colormap = (Colormap)0;
+ _glfwWin.context = (GLXContext)NULL;
+ _glfwWin.window = (Window)0;
+ _glfwWin.pointerGrabbed = GL_FALSE;
+ _glfwWin.pointerHidden = GL_FALSE;
+ _glfwWin.keyboardGrabbed = GL_FALSE;
+ _glfwWin.overrideRedirect = GL_FALSE;
+ _glfwWin.FS.modeChanged = GL_FALSE;
+ _glfwWin.Saver.changed = GL_FALSE;
+ _glfwWin.refreshRate = wndconfig->refreshRate;
+ _glfwWin.windowNoResize = wndconfig->windowNoResize;
+
+ _glfwWin.wmDeleteWindow = None;
+ _glfwWin.wmPing = None;
+ _glfwWin.wmState = None;
+ _glfwWin.wmStateFullscreen = None;
+ _glfwWin.wmActiveWindow = None;
+
+ // As the 2.x API doesn't understand multiple display devices, we hardcode
+ // this choice and hope for the best
+ _glfwWin.screen = DefaultScreen( _glfwLibrary.display );
+ _glfwWin.root = RootWindow( _glfwLibrary.display, _glfwWin.screen );
+
+ // Create the invisible cursor for hidden cursor mode
+ _glfwWin.cursor = createNULLCursor( _glfwLibrary.display, _glfwWin.root );
+
+ initGLXExtensions();
+
+ // Choose the best available fbconfig
+ {
+ unsigned int fbcount;
+ _GLFWfbconfig *fbconfigs;
+ const _GLFWfbconfig *result;
+
+ fbconfigs = getFBConfigs( &fbcount );
+ if( !fbconfigs )
+ {
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ result = _glfwChooseFBConfig( fbconfig, fbconfigs, fbcount );
+ if( !result )
+ {
+ free( fbconfigs );
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ closest = *result;
+ free( fbconfigs );
+ }
+
+ if( !createContext( wndconfig, (GLXFBConfigID) closest.platformID ) )
+ {
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ if( !createWindow( width, height, wndconfig ) )
+ {
+ _glfwPlatformCloseWindow();
+ return GL_FALSE;
+ }
+
+ if( wndconfig->mode == GLFW_FULLSCREEN )
+ {
+#if defined( _GLFW_HAS_XRANDR )
+ // Request screen change notifications
+ if( _glfwLibrary.XRandR.available )
+ {
+ XRRSelectInput( _glfwLibrary.display,
+ _glfwWin.window,
+ RRScreenChangeNotifyMask );
+ }
+#endif
+ enterFullscreenMode();
+ }
+
+ // Process the window map event and any other that may have arrived
+ _glfwPlatformPollEvents();
+
+ // Retrieve and set initial cursor position
+ {
+ Window window, root;
+ int windowX, windowY, rootX, rootY;
+ unsigned int mask;
+
+ XQueryPointer( _glfwLibrary.display,
+ _glfwWin.window,
+ &root,
+ &window,
+ &rootX, &rootY,
+ &windowX, &windowY,
+ &mask );
+
+ // TODO: Probably check for some corner cases here.
+
+ _glfwInput.MousePosX = windowX;
+ _glfwInput.MousePosY = windowY;
+ }
+
+ // Connect the context to the window
+ glXMakeCurrent( _glfwLibrary.display, _glfwWin.window, _glfwWin.context );
+
+ return GL_TRUE;
+}
+
+
+//========================================================================
+// Properly kill the window/video display
+//========================================================================
+
+void _glfwPlatformCloseWindow( void )
+{
+ if( _glfwWin.fullscreen )
+ {
+ leaveFullscreenMode();
+ }
+
+ if( _glfwWin.context )
+ {
+ // Release and destroy the context
+ glXMakeCurrent( _glfwLibrary.display, None, NULL );
+ glXDestroyContext( _glfwLibrary.display, _glfwWin.context );
+ _glfwWin.context = NULL;
+ }
+
+ if( _glfwWin.visual )
+ {
+ XFree( _glfwWin.visual );
+ _glfwWin.visual = NULL;
+ }
+
+ if( _glfwWin.window )
+ {
+ XUnmapWindow( _glfwLibrary.display, _glfwWin.window );
+ XDestroyWindow( _glfwLibrary.display, _glfwWin.window );
+ _glfwWin.window = (Window) 0;
+ }
+
+ if( _glfwWin.colormap )
+ {
+ XFreeColormap( _glfwLibrary.display, _glfwWin.colormap );
+ _glfwWin.colormap = (Colormap) 0;
+ }
+
+ if( _glfwWin.cursor )
+ {
+ XFreeCursor( _glfwLibrary.display, _glfwWin.cursor );
+ _glfwWin.cursor = (Cursor) 0;
+ }
+}
+
+
+//========================================================================
+// Set the window title
+//========================================================================
+
+void _glfwPlatformSetWindowTitle( const char *title )
+{
+ // Set window & icon title
+ XStoreName( _glfwLibrary.display, _glfwWin.window, title );
+ XSetIconName( _glfwLibrary.display, _glfwWin.window, title );
+}
+
+
+//========================================================================
+// Set the window size
+//========================================================================
+
+void _glfwPlatformSetWindowSize( int width, int height )
+{
+ int mode = 0, rate, sizeChanged = GL_FALSE;
+ XSizeHints *sizehints;
+
+ rate = _glfwWin.refreshRate;
+
+ if( _glfwWin.fullscreen )
+ {
+ // Get the closest matching video mode for the specified window size
+ mode = _glfwGetClosestVideoMode( _glfwWin.screen, &width, &height, &rate );
+ }
+
+ if( _glfwWin.windowNoResize )
+ {
+ // Update window size restrictions to match new window size
+
+ sizehints = XAllocSizeHints();
+ sizehints->flags = 0;
+
+ sizehints->min_width = sizehints->max_width = width;
+ sizehints->min_height = sizehints->max_height = height;
+
+ XSetWMNormalHints( _glfwLibrary.display, _glfwWin.window, sizehints );
+ XFree( sizehints );
+ }
+
+ // Change window size before changing fullscreen mode?
+ if( _glfwWin.fullscreen && (width > _glfwWin.width) )
+ {
+ XResizeWindow( _glfwLibrary.display, _glfwWin.window, width, height );
+ sizeChanged = GL_TRUE;
+ }
+
+ if( _glfwWin.fullscreen )
+ {
+ // Change video mode, keeping current refresh rate
+ _glfwSetVideoModeMODE( _glfwWin.screen, mode, _glfwWin.refreshRate );
+ }
+
+ // Set window size (if not already changed)
+ if( !sizeChanged )
+ {
+ XResizeWindow( _glfwLibrary.display, _glfwWin.window, width, height );
+ }
+}
+
+
+//========================================================================
+// Set the window position.
+//========================================================================
+
+void _glfwPlatformSetWindowPos( int x, int y )
+{
+ XMoveWindow( _glfwLibrary.display, _glfwWin.window, x, y );
+}
+
+
+//========================================================================
+// Window iconification
+//========================================================================
+
+void _glfwPlatformIconifyWindow( void )
+{
+ if( _glfwWin.overrideRedirect )
+ {
+ // We can't iconify/restore override-redirect windows, as that's
+ // performed by the window manager
+ return;
+ }
+
+ XIconifyWindow( _glfwLibrary.display, _glfwWin.window, _glfwWin.screen );
+}
+
+
+//========================================================================
+// Window un-iconification
+//========================================================================
+
+void _glfwPlatformRestoreWindow( void )
+{
+ if( _glfwWin.overrideRedirect )
+ {
+ // We can't iconify/restore override-redirect windows, as that's
+ // performed by the window manager
+ return;
+ }
+
+ XMapWindow( _glfwLibrary.display, _glfwWin.window );
+}
+
+
+//========================================================================
+// Swap OpenGL buffers and poll any new events
+//========================================================================
+
+void _glfwPlatformSwapBuffers( void )
+{
+ // Update display-buffer
+ glXSwapBuffers( _glfwLibrary.display, _glfwWin.window );
+}
+
+
+//========================================================================
+// Set double buffering swap interval
+//========================================================================
+
+void _glfwPlatformSwapInterval( int interval )
+{
+ if( _glfwWin.has_GLX_SGI_swap_control )
+ {
+ _glfwWin.SwapIntervalSGI( interval );
+ }
+}
+
+
+//========================================================================
+// Read back framebuffer parameters from the context
+//========================================================================
+
+void _glfwPlatformRefreshWindowParams( void )
+{
+ int dummy;
+ GLXFBConfig *fbconfig;
+#if defined( _GLFW_HAS_XRANDR )
+ XRRScreenConfiguration *sc;
+#elif defined( _GLFW_HAS_XF86VIDMODE )
+ XF86VidModeModeLine modeline;
+ int dotclock;
+ float pixels_per_second, pixels_per_frame;
+#endif
+ int attribs[] = { GLX_FBCONFIG_ID, _glfwWin.fbconfigID, None };
+
+ if( _glfwWin.has_GLX_SGIX_fbconfig )
+ {
+ fbconfig = _glfwWin.ChooseFBConfigSGIX( _glfwLibrary.display,
+ _glfwWin.screen,
+ attribs,
+ &dummy );
+ }
+ else
+ {
+ fbconfig = glXChooseFBConfig( _glfwLibrary.display,
+ _glfwWin.screen,
+ attribs,
+ &dummy );
+ }
+
+ if( fbconfig == NULL )
+ {
+ // This should never ever happen
+ // TODO: Figure out what to do when this happens
+ fprintf( stderr, "Cannot find known GLXFBConfig by ID. "
+ "This cannot happen. Have a nice day.\n");
+ abort();
+ }
+
+ // There is no clear definition of an "accelerated" context on X11/GLX, and
+ // true sounds better than false, so we hardcode true here
+ _glfwWin.accelerated = GL_TRUE;
+
+ _glfwWin.redBits = getFBConfigAttrib( *fbconfig, GLX_RED_SIZE );
+ _glfwWin.greenBits = getFBConfigAttrib( *fbconfig, GLX_GREEN_SIZE );
+ _glfwWin.blueBits = getFBConfigAttrib( *fbconfig, GLX_BLUE_SIZE );
+
+ _glfwWin.alphaBits = getFBConfigAttrib( *fbconfig, GLX_ALPHA_SIZE );
+ _glfwWin.depthBits = getFBConfigAttrib( *fbconfig, GLX_DEPTH_SIZE );
+ _glfwWin.stencilBits = getFBConfigAttrib( *fbconfig, GLX_STENCIL_SIZE );
+
+ _glfwWin.accumRedBits = getFBConfigAttrib( *fbconfig, GLX_ACCUM_RED_SIZE );
+ _glfwWin.accumGreenBits = getFBConfigAttrib( *fbconfig, GLX_ACCUM_GREEN_SIZE );
+ _glfwWin.accumBlueBits = getFBConfigAttrib( *fbconfig, GLX_ACCUM_BLUE_SIZE );
+ _glfwWin.accumAlphaBits = getFBConfigAttrib( *fbconfig, GLX_ACCUM_ALPHA_SIZE );
+
+ _glfwWin.auxBuffers = getFBConfigAttrib( *fbconfig, GLX_AUX_BUFFERS );
+ _glfwWin.stereo = getFBConfigAttrib( *fbconfig, GLX_STEREO ) ? 1 : 0;
+
+ // Get FSAA buffer sample count
+ if( _glfwWin.has_GLX_ARB_multisample )
+ {
+ _glfwWin.samples = getFBConfigAttrib( *fbconfig, GLX_SAMPLES );
+ }
+ else
+ {
+ _glfwWin.samples = 0;
+ }
+
+ // Default to refresh rate unknown (=0 according to GLFW spec)
+ _glfwWin.refreshRate = 0;
+
+ // Retrieve refresh rate if possible
+#if defined( _GLFW_HAS_XRANDR )
+ if( _glfwLibrary.XRandR.available )
+ {
+ sc = XRRGetScreenInfo( _glfwLibrary.display, _glfwWin.root );
+ _glfwWin.refreshRate = XRRConfigCurrentRate( sc );
+ XRRFreeScreenConfigInfo( sc );
+ }
+#elif defined( _GLFW_HAS_XF86VIDMODE )
+ if( _glfwLibrary.XF86VidMode.available )
+ {
+ // Use the XF86VidMode extension to get current video mode
+ XF86VidModeGetModeLine( _glfwLibrary.display, _glfwWin.screen,
+ &dotclock, &modeline );
+ pixels_per_second = 1000.0f * (float) dotclock;
+ pixels_per_frame = (float) modeline.htotal * modeline.vtotal;
+ _glfwWin.refreshRate = (int)(pixels_per_second/pixels_per_frame+0.5);
+ }
+#endif
+
+ XFree( fbconfig );
+}
+
+
+//========================================================================
+// Poll for new window and input events
+//========================================================================
+
+void _glfwPlatformPollEvents( void )
+{
+ GLboolean closeRequested = GL_FALSE;
+
+ // Flag that the cursor has not moved
+ _glfwInput.MouseMoved = GL_FALSE;
+
+ // Process all pending events
+ while( XPending( _glfwLibrary.display ) )
+ {
+ if( processSingleEvent() )
+ {
+ closeRequested = GL_TRUE;
+ }
+ }
+
+ // Did we get mouse movement in fully enabled hidden cursor mode?
+ if( _glfwInput.MouseMoved && _glfwWin.pointerHidden )
+ {
+ _glfwPlatformSetMouseCursorPos( _glfwWin.width/2,
+ _glfwWin.height/2 );
+ }
+
+ if( closeRequested && _glfwWin.windowCloseCallback )
+ {
+ closeRequested = _glfwWin.windowCloseCallback();
+ }
+ if( closeRequested )
+ {
+ glfwCloseWindow();
+ }
+}
+
+
+//========================================================================
+// Wait for new window and input events
+//========================================================================
+
+void _glfwPlatformWaitEvents( void )
+{
+ XEvent event;
+
+ // Block waiting for an event to arrive
+ XNextEvent( _glfwLibrary.display, &event );
+ XPutBackEvent( _glfwLibrary.display, &event );
+
+ _glfwPlatformPollEvents();
+}
+
+
+//========================================================================
+// Hide mouse cursor (lock it)
+//========================================================================
+
+void _glfwPlatformHideMouseCursor( void )
+{
+ // Hide cursor
+ if( !_glfwWin.pointerHidden )
+ {
+ XDefineCursor( _glfwLibrary.display, _glfwWin.window, _glfwWin.cursor );
+ _glfwWin.pointerHidden = GL_TRUE;
+ }
+
+ // Grab cursor to user window
+ if( !_glfwWin.pointerGrabbed )
+ {
+ if( XGrabPointer( _glfwLibrary.display, _glfwWin.window, True,
+ ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask, GrabModeAsync, GrabModeAsync,
+ _glfwWin.window, None, CurrentTime ) ==
+ GrabSuccess )
+ {
+ _glfwWin.pointerGrabbed = GL_TRUE;
+ }
+ }
+}
+
+
+//========================================================================
+// Show mouse cursor (unlock it)
+//========================================================================
+
+void _glfwPlatformShowMouseCursor( void )
+{
+ // Un-grab cursor (only in windowed mode: in fullscreen mode we still
+ // want the mouse grabbed in order to confine the cursor to the window
+ // area)
+ if( _glfwWin.pointerGrabbed )
+ {
+ XUngrabPointer( _glfwLibrary.display, CurrentTime );
+ _glfwWin.pointerGrabbed = GL_FALSE;
+ }
+
+ // Show cursor
+ if( _glfwWin.pointerHidden )
+ {
+ XUndefineCursor( _glfwLibrary.display, _glfwWin.window );
+ _glfwWin.pointerHidden = GL_FALSE;
+ }
+}
+
+
+//========================================================================
+// Set physical mouse cursor position
+//========================================================================
+
+void _glfwPlatformSetMouseCursorPos( int x, int y )
+{
+ // Store the new position so we can recognise it later
+ _glfwInput.CursorPosX = x;
+ _glfwInput.CursorPosY = y;
+
+ XWarpPointer( _glfwLibrary.display, None, _glfwWin.window, 0,0,0,0, x, y );
+}
+
diff --git a/readme.html b/readme.html
new file mode 100644
index 00000000..e304949d
--- /dev/null
+++ b/readme.html
@@ -0,0 +1,821 @@
+
+
+
+
+
+ GLFW Readme File
+
+
+
+
+
+GLFW 2.7 Lite
+
+
+ - Introduction
+ - Compiling GLFW and the example programs
+ - Installing GLFW
+ - Using GLFW
+ - Frequently Asked Questions
+ - Version history
+ - Directory structure of the GLFW distribution
+ - Contacting the project
+ - Acknowledgements
+
+
+
+1. Introduction
+
+Welcome to version 2.7 Lite of the GLFW OpenGL framework. GLFW is
+a free, open source, portable framework for OpenGL application development. In
+short, it is a library that constitutes a powerful API for handling operating
+system specific tasks, such as opening an OpenGL window, reading keyboard and
+mouse input, and more.
+
+Please note that this is the Lite version of GLFW, which
+means that some areas of functionality present in 2.x mainline versions of GLFW
+have been removed.
+
+
+2. Compiling GLFW and the example programs
+
+To compile GLFW and the accompanying example programs, you will need the CMake build system.
+
+
+3. Installing GLFW
+
+A rudimentary installation target is provided for all supported platforms
+via the CMake build system.
+
+For Unix-like platforms, the command is:
+
+$ make install
+
+Note that you may need to run this command as root or via
+sudo(1)
in order to install GLFW into the various system
+directories.
+
+For Visual C++ and other integrated development environments, an installation
+target should appear in the by CMake generated project files.
+
+
+4. Using GLFW
+
+There are two aspects to using GLFW:
+
+
+
+ - How the GLFW API works
+ - How to compile programs that use GLFW
+
+
+The first point is covered in the GLFW
+Users Guide and the GLFW Reference
+Manual, and we suggest that you read at least the Users Guide, since
+it's a good introduction to the GLFW API.
+
+Designing and compiling programs that use GLFW is not very difficult.
+A few rules for successfully designing GLFW-based programs are presented
+in the following sections.
+
+4.1 Include GL/glfw.h
+
+In your program, you should include GL/glfw.h
like this:
+
+#include <GL/glfw.h>
+
+This include file defines all the necessary constants, types and prototypes
+that are used to interact with the GLFW API. It also includes
+GL/gl.h
and GL/glu.h
, and - it defines all the
+necessary constants and types that are necessary for OpenGL to work on
+different platforms.
+
+For instance, under Windows you are normally required to include
+windows.h
before you include GL/gl.h
. If you write
+such a program, it would not compile under e.g. Linux since
+windows.h
does not exist under Linux. GL/glfw.h
+takes care of these things for you. Note however that it does not actually
+include windows.h
, it merely mimics the parts of it that are
+needed for GL/gl.h
and GL/glu.h
(this way we do not
+get the thousands of constants, types and prototypes that could otherwise
+possibly interfere with our own declarations).
+
+In other words:
+
+ - Do not include
GL/gl.h
or GL/glu.h
+ (GLFW does it for you)
+ - Do not include
windows.h
unless you need
+ to write Win32-specific code
+ - If you do need to include
windows.h
, do it
+ before including GL/glfw.h
.
+
+
+4.2 Link with the correct libraries
+
+4.2.1 Windows static library
+
+If you link with the static version of GLFW, it is also necessary to
+link with some system libraries that GLFW uses.
+
+When linking a program under Windows that uses the static version of GLFW,
+you must also link with the following libraries: opengl32
,
+user32
and kernel32
. Some of these libraries may be
+linked with by default by your compiler. In the table below you can see the
+minimum required link options for each supported Windows compiler (you may want
+to add other libraries as well, such as glu32
):
+
+
+
+
+ Borland C++ Builder |
+ glfw.lib opengl32.lib |
+
+
+ Cygwin |
+ See Unix static library below |
+
+
+ LCC-Win32 |
+ glfw.lib opengl32.lib |
+
+
+ Microsoft Visual C++ |
+ glfw.lib opengl32.lib user32.lib |
+
+
+ MinGW32 |
+ -lglfw -lopengl32 |
+
+
+ OpenWatcom |
+ glfw.lib opengl32.lib user32.lib |
+
+
+ Pelles C |
+ glfw.lib opengl32.lib user32.lib kernel32.lib |
+
+
+
+
+4.2.2 Windows DLL
+
+To compile a program that uses the DLL version of GLFW, you need to define
+the GLFW_DLL
constant. This can either be done with a compiler switch,
+typically by adding -DGLFW_DLL
to the list of compiler options. You can
+also do it by adding the following line to all your source files that include
+glfw.h
, before including it:
+
+#define GLFW_DLL
+
+When linking a program under Windows that uses the DLL version of GLFW,
+the only library you need to link with for GLFW to work is glfwdll
.
+In the table below you can see the minimum required link options for each
+supported Windows compiler (you may want to add other libraries as well,
+such as opengl32
and glu32
):
+
+
+
+
+ Borland C++ Builder |
+ glfwdll.lib |
+
+
+ Cygwin |
+ -lglfwdll |
+
+
+ LCC-Win32 |
+ glfwdll.lib |
+
+
+ Microsoft Visual C++ |
+ glfwdll.lib |
+
+
+ MinGW32 |
+ -lglfwdll |
+
+
+ OpenWatcom |
+ glfwdll.lib |
+
+
+ Pelles C |
+ glfwdll.lib |
+
+
+
+4.2.3 Unix static library
+
+GLFW now supports
+pkgconfig,
+and a libglfw.pc file is generated and installed when you install the library.
+For systems that do not provide pkgconfig, you should look in this file for the
+proper compile and link flags for your system, as determined by compile.sh at
+compile time.
+
+A typical compile and link command line may look like this (using GCC):
+
+gcc `pkg-config --cflags libglfw` -o myprog myprog.c `pkg-config --libs libglfw`
+
+If you use GLU functions in your program then you should also add the
+-lGLU
flag.
+
+
+
4.2.5 Mac OS X static library
+
+When compiling and linking a program under Mac OS X that uses GLFW, you
+must also link with the following frameworks: Carbon.framework
,
+AGL.framework
and OpenGL.framework
.
+
+
If you are using Xcode, you simply add the GLFW library
+libglfw.a
and these frameworks to your project. If, however, you
+are building your program from the command line, there are two methods for
+correctly linking your GLFW program.
+
+GLFW now supports pkgconfig, and a pkgconfig
+file named libglfw.pc is generated and installed when you install the library.
+You can find pkgconfig in most packaging systems, such as Fink and DarwinPorts, so if you have one
+of them installed, simply install pkgconfig. Once you have pkgconfig available,
+the command line for compiling and linking your program is:
+
+gcc `pkg-config --cflags libglfw` -o myprog myprog.c `pkg-config --libs libglfw`
+
+If you do not wish to use pkgconfig, you will need to add the required
+frameworks and libraries to your command line using the -l
and
+-framework
switches, i.e.:
+
+gcc -o myprog myprog.c -lglfw -framework Carbon -framework AGL -framework OpenGL
+
+Note that you do not add the .framework extension to a framework when adding
+it from the command line.
+
+These frameworks contain all GL and GLU functions, so there is no need to
+add additional libraries or frameworks when using GLU functionality. Also note
+that even though your machine may have Unix-style GL libraries, they are for
+use with the X Window System, and will not work with the Mac OS X
+native version of GLFW.
+
+
+9. Frequently Asked Questions
+
+
+5. Version history
+
+2.7 Lite
+
+ - Removed all threading support
+ - Removed all image and texture loading support
+ - Removed all build files not related to CMake
+ - Removed D, Delphi and Lua bindings
+ - Imported CMake work from pre-3.0 branch
+
+
+2.7
+
+ - Added
GLFW_OPENGL_VERSION_MAJOR
,
+ GLFW_OPENGL_VERSION_MINOR
and
+ GLFW_OPENGL_FORWARD_COMPAT
hints for versioned context
+ creation support
+ - Added
GLFW_NO_GLU
macro for disabling the inclusion of the
+ GLU header
+ - Added the proper DEF file to the Visual C++ DLL project file
+ - Added a rudimentary joystick API testing example
+ - Changed all comments in public header file to plain C style
+ - Removed all deprecated platforms
+ - [X11] Added
x11-distro-install
install target, intended for packagers
+ - [X11] Removed support for GLX version 1.3 and below
+ - [X11] Bugfix: Misspelt struct member in XF86VidMode code path
+ - [MacOSX] Bugfix: Key repeat events were ignored on 10.5 Leopard
+ - [Win32] Bugfix: Improper use of wParam for
WM_SYSCOMMAND
+ - [Win32] Bugfix: Derivatives of stream.c not cleaned up by compile.bat
+ - [Win32] Bugfix: Pointer for
GetExtensionsStringARB
was not initialized
+ - [Win32] Bugfix: Updated API version in makefiles
+
+
+2.6
+
+ - Added
GLFW_FSAA_SAMPLES
multi-sampling hint
+ - Added
GLFW_WINDOW_NO_RESIZE
hint for non-resizable windows
+ - Added install targets for all Unix-like build targets
+ - Added
glfwReadMemoryImage
function for creating a
+ GLFWImage
object from an image file in a memory buffer
+ - Added
glfwLoadMemoryTexture2D
function for decoding an image
+ file in a memory buffer into a texture
+ - Added
glfwLoadTextureImage2D
function for loading a
+ GLFWImage
object into a texture
+ - Added cross-compilation support for MinGW under a Unix-like host
+ - D bindings updated and all examples ported to modern D
+ - Delphi bindings updated to reflect API additions
+ - Bugfix: The interaction between key repeat and window focus code caused duplicate presses
+ - Bugfix: The mouse position was not properly updated when re-enabling the mouse cursor
+ - [Win32] Added pkgconfig file generation for Cygwin
+ - [Win32] Added version number to window class name
+ - [Win32] Added optional loading of user provided window icon resource
+ - [Win32] Bugfix: Very small sleep periods were forced to higher value
+ - [Win32] Bugfix: The nmake makefile did not handle paths with spaces correctly
+ - [Win32] Bugfix: Removed assembly RDTSC timing code
+ - [Win32] Bugfix: Hidden cursor was not clipped to windowed windows
+ - [X11] Added XRandR code path for fullscreen windows
+ - [X11] Added building of shared library
+ - [X11] Added ICCCM WM fullscreen hints
+ - [X11] Added support for the
_NET_WM_PING
protocol
+ - [X11] Added pkgconfig file generation
+ - [X11] Added setting of WM size hints
+ - [X11] Bugfix: Removed assembly RDTSC timing code
+ - [X11] Bugfix: Window re-opening now works properly (including fullscreen windows)
+ - [X11] Bugfix: Potential crash bug in video mode matching code
+ - [X11] Bugfix: Static buffers imposed an invisible limit on reported video mode count
+ - [X11] Bugfix: Interaction with certain window managers when setting input
+ focus would cause termination with a BadMatch error
+ - [X11] Bugfix: Keypad keys did not trigger the character callback
+ - [MacOSX] Added pkgconfig file generation
+ - [MacOSX] Added building of shared library
+ - [MacOSX] Added building of Universal Binary libraries
+ - [MacOSX] Replaced fullscreen code path with CGL version
+ - [MacOSX] Bugfix: Binaries without bundles or resource forks now interact
+ properly with the WM
+ - [MacOSX] Bugfix: Replaced Carbon event time source with
gettimeofday
+ - [MacOSX] Bugfix: Added code to minimize the dreaded OpenGL application startup jump
+ - [MacOSX] Bugfix: Fixed broken implementation of
+
glfwSetMousePos
for windowed mode
+ - [MacOSX] Bugfix: Fixed broken implementation of hidden cursor
+ - [MacOSX] Bugfix: Capturing all displays and not just the main one
+ - [AmigaOS] Obsoleted platform due to lack of maintainer and community interest
+ - [DOS] Obsoleted platform due to lack of maintainer and community interest
+
+
+2.5
+
+ - Added the function glfwWaitEvents
+ - Added window close callback, which enables a program to prevent a user
+ from closing a window with the window manager
+ - Added window refresh callback, which is called when the window needs
+ to be refreshed
+ - Added support for loading alpha textures (GLFW_ALPHA_MAP_BIT)
+ - Added support for the Lua programming language
+ - Added support for the D programming language
+ - Added support for the Pelles C compiler for Windows
+ - Added API level support for up to eight mouse buttons
+ - [Win32] Added support for up to five mouse buttons
+ - [Win32] Mouse down events capture mouse input
+ - [Win32] Bugfix: The DLL now exports glfwSetTime
+ - [Win32] Fix: The GLFW window is now placed in the upper left corner
+ of the desktop working area
+ - [Win32/X11] Bugfix: More robust check for SwapInterval
+ - [X11] Added support for USB joysticks under Linux (/dev/input/js*)
+ - [X11] Bugfix: Added support for GLX extensions in glfwExtensionSupported
+ - [X11] Bugfix: More robust fullscreen mode (?)
+ - [X11] Bugfix: Runtime check of XF86VidMode support for the active
+ display
+ - [X11] Bugfix: Some mouse button events were reported incorrectly
+ - [MacOSX] Added support for the input char callback.
+ - [MacOSX] Added video mode validation and duplicate elimination.
+ - [MacOSX] Switched to a new MakeBundle.sh script.
+ - [MacOSX] Added emulation of the window refresh callback.
+ - [MacOSX] Bugfix: The window and its associated resources are now
+ properly released.
+ - [MacOSX] Bugfix: Removed support for more than eight mouse buttons.
+ - [x86 CPUs] Improved Intel mobile CPU detection (e.g. disables RDTSC
+ timing on Centrino systems)
+
+
+2.4.2
+
+ - Preliminary native Mac OS X support (via the Carbon interface)
+ - Preliminary DOS support (DJGPP + Mesa)
+ - Changed license to the zlib license (almost identical to the previous
+ GLFW license), so now GLFW is OSI Certified
+ - Rewrote the GLFW documentation in LaTeX, meaning several improvements
+ (both visual and practical)
+ - Added the support folder to the distribution, which includes
+ support for various languages
+ - [Win32] Added OpenWatcom compiler support (thanks Sebastian
+ Schuberth!)
+ - [Win32] Changed fallback timer from GetTickCount to timeGetTime,
+ which usually provides better resolution
+ - [Win32] Bugfix: Accumulator buffer selection should be more
+ robust
+ - [Win32] Bugfix: If stereo rendering is requested, and no stereo pixel
+ format could be created, glfwOpenWindow now fails
+ - [Win32] Bugfix: glfwSetWindowSize now sets the size of the client
+ area, NOT the entire window, meaning that there is a 1:1 relationship
+ between glfwSetWindowSize and glfwGetWindowSize
+ - [X11] Added FreeBSD and QNX support
+ - [X11] Added support for non-pthread capable systems
+ - [X11] Hopefully more robust configuration script (compile.sh)
+ - [X11] Bugfix: When mouse cursor is hidden, mouse sensitivity is no
+ longer degraded
+ - [X11] Bugfix: Source files EOL was PC style (CR/LF) in 2.4.1 (blame
+ my WinCVS configuration)
+ - [X11] Bugfix: When a GLFW window is closed, input focus is properly
+ released
+ - [X11] Bugfix: Iconification of fullscreen windows should now work
+ properly
+ - [x86 CPUs] Improved RDTSC timing (e.g. RDTSC support on single-CPU
+ Intel Hyper-Threading enabled systems)
+ - [AmigaOS] Added joystick support
+ - [AmigaOS] Mouse cursor positioning is now implemented
+ - [AmigaOS] Added support for Geek Gadgets GCC
+ - [AmigaOS] Bugfix: glfwGetWindowParam now returns proper values for
+ all parameters (except for GLFW_ACCELERATED)
+
+
+2.4.1
+
+ - Added AmigaOS support (preliminary)
+ - GLFW for the X Window System now works under Mac OS X
+ - [Win32] Bugfix: glfwWaitCond treated the timeout as milliseconds
+ instead of seconds
+ - [X11] Bugfix: GLFW should now compile under IRIX v5.3
+ - [X11] Bugfix: GLFW should now compile with Kylix
+
+
+2.4
+
+ - Major source code rearrangement - much code is now shared between
+ different platforms, and it should be easier to port GLFW to new
+ platforms
+ - Added a Unicode keyboard text input interface (CharCallback)
+ - Keyboard key input is now slightly more internationalized: GLFW now
+ uses 8-bit ISO-8859-1 encoding for keys representing printable
+ characters (e.g. "Ö", "§", etc.), as
+ opposed to the previous 7-bit US-ASCII encoding
+ - Added more key constants (F13-F25, keypad '=')
+ - Added an enable/disable switch for automatic event polling from
+ glfwSwapBuffers
+ - [X11] Added support for sysctl for querying the number of processors
+ in the system (if POSIX sysconf is not supported)
+ - [X11] Bugfix: compile.sh now works with Sun sh (and hopefully others
+ too)
+ - [X11] Bugfix: compile.sh now detects the need for -ldl when dlopen is
+ used
+ - [Win32] Bugfix: When closing a fullscreen window under Win 9x/NT4,
+ the task bar icon now disappears properly
+ - [Win32] Bugfix: GLFW should now compile on a wider range of MSVC
+ compilers (e.g. .NET) - Thanks Tim Little!
+
+
+2.3.2
+
+ - Removed the silly limitation of 100 threads (the thread information
+ is now kept in a linked list)
+ - General source cleanup (window state is now kept in a single
+ struct, plus some other minor changes)
+ - [X11] Added Solaris gethrtime() support (not tested yet), which
+ should give an improved timer for Sun/Solaris stations
+ - [X11] Some fixes to the 'compile.sh' script (-O for non-gcc compilers
+ and 'make x11-gcc' should now really force GCC)
+
+
+2.3.1
+
+ - [X11] A minimalist configuration script was added that solves the
+ issue with glXGetProcAddressARB, and unifies all Unix/X11 Makefiles
+ into one template Makefile (well, one for GLFW, and one for the
+ examples)
+
+
+2.3
+
+ - Added OpenGL stereo rendering support
+ - Added a function for parsing the OpenGL version string
+ (glfwGetGLVersion)
+ - [x86] Bugfix: Hopefully the CPU core clock dependent timer RDTSC will
+ never be used on CPUs with variable core frequencies anymore
+ - [X11] Bugfix: GLFW could create stereo rendering capable windows,
+ even if it was not requested (GLFW 2.2.x did not support selection
+ of stereo rendering)
+ - [X11] Bugfix: glfwGetProcAddress returned NULL on most systems (even
+ on those that supported glXGetProcAddressARB). Now GLFW assumes that
+ glXGetProcAddressARB is supported on all systems, which solves the
+ bug, but may result in compiler errors on some systems (please let me
+ know if you have any related problems).
+
+
+2.2.3
+
+ - Bugfix: Checking for GL_SGIS_generate_mipmap is more robust
+ - Bugfix: glfwLoadTexture2D will now fail if no window is opened
+ - [Win32] Bugfix: Right shift was not detected under Win 9x/ME (it is
+ still not as good as under NT/2K/XP, but at least you get right
+ shifts)
+ - [X11] Bugfix: Visuals are now selected more accurately. For instance,
+ glfwOpenWindow will no longer fail if you request a 24-bit color
+ buffer if only 16-bit color visuals are available (which means that
+ pong3d should work on 16-bit displays).
+
+
+2.2.2
+
+ - [Win32] Bugfix: Windows did not always get focus (this was a tough
+ one!)
+ - [Win32] Bugfix: glfwGetWindowParam did not work with
+ GLFW_ACCUM_*_BITS or GLFW_AUX_BUFFERS
+ - [X11] Bugfix: Linux joystick Y axis positions were reversed
+
+
+2.2.1
+
+ - [X11] Added joystick support for Linux
+
+
+2.2
+
+ - Added joystick support (only supported under Windows so far)
+ - Added joystick controls to pong3d.c (only 3 more lines of code)
+ - Added glfwOpenWindowHint() function
+ - It is now possible to specify a desired vertical monitor refresh
+ rate (for fullscreen windows)
+ - It is now possible to request an accumulator buffer and auxiliary
+ buffers
+ - Added glfwSetTime() function
+ - Added a GLFW conversion of the MESA/GLUT gears.c demo to the example
+ programs
+ - [Win32] gdi32.dll and winmm.dll are now loaded dynamically when
+ glfwInit() is called. This means that there is no need to link with
+ gdi32.lib or winmm.lib when using the static version of GLFW, which
+ should make GLFW usage more convenient.
+ - [Win32] Bugfix: Greatly improved keyboard input (detect left/right
+ CTRL etc)
+ - [Win32] Bugfix: glfwExtensionSupported now detects all WGL extensions
+ (e.g. WGL_ARB_pbuffer)
+ - [Win32] Bugfix: Mouse cursor was not re-hidden when a GLFW window was
+ deselected and then selected again (with ALT+TAB)
+ - [X11] Bugfix: Minor bug in the SGI timer - and ugly (unintended) SGI
+ timer debug info removed
+ - [X11] Bugfix: glfwGetDesktopMode and glfwGetVideoModes no longer give
+ segmentation faults if no X server is available
+
+
+2.1
+
+ - Added image and texture loading capabilities (support for the TGA
+ file format at the moment)
+ - Added a new example program (mipmaps.c) for showing off the automatic
+ mipmap generation and texture loading capabilities of GLFW 2.1
+ - Removed the separate TGA loader (tga.c in the examples directory)
+ since texture loading is supported natively by GLFW. Also updated the
+ Pong3D demo to use GLFW texture loading instead of tga.c.
+ - Improved keyboard handling (e.g. numeric keypad keys can be
+ detected)
+ - Added a new example program, keytest.c
+ - Changed the GLFWvidmode structure and the corresponding API functions
+ to report pure color bits instead of the confusing (and unportable)
+ "BPP" field
+ - Changed glfwSetWindowSize so that it operates in fullscreen mode
+ too
+ - Added mouse wheel support under Windows (not Win95) and X11
+ - Added window iconification functions (glfwInconifyWindow and
+ glfwRestoreWindow)
+ - Improved iconification and deactivation handling under both Windows
+ and X11
+ - Made it possible to turn on/off key repeat (the default is now no key
+ repeat)
+ - Added SGI hardware timer support (CLOCK_SGI_CYCLE) for improved
+ timer resolution for SGI computers
+ - Added support for the free Borland C++ Builder 5.x compiler for
+ Windows
+ - Made it possible to compiler GLFW as a Windows DLL using any of the
+ supported compilers
+ - Some constants have changed names (e.g. GLFW_REDBITS is now called
+ GLFW_RED_BITS)
+ - Updated GLFW documentation (GLFW Users Guide and GLFW Reference
+ Manual) to reflect the changes in the API
+ - [Win32] Bugfix: Corrected Cygwin toplevel makefile entry
+ - [Win32] Bugfix: Fixed event lag bug
+ - [Win32] Bugfix: Fixed Radeon 8500 crash
+ - [X11] Bugfix: Fixed the window close bug
+ - [X11] Bugfix: Iconification/deactivation is now detected
+ - [X11] Bugfix: Non-OpenGL visuals are not listed anymore
+ - [XFree86] Bugfix: Undesired video mode changes are now prevented
+
+
+2.0.3
+
+ - Added precise CPU cycle based timing support (RDTSC) for x86
+ CPUs (under both Windows and Unix)
+ - Added a makefile option for building for Windows with Cygwin
+ - Corrected the CC for Unix/X11 makefiles (-Wall is usually not a
+ supported flag for CC, so it was removed from the CFLAGS list)
+
+
+2.0.2
+
+ - Added a makefile option for building for X11 with 'cc' rather than
+ 'gcc' (useful for IRIX users for instance).
+ - [Win32] Bugfix: Mouse coordinates are now relative to the window
+ upper left corner, which also means that disabling the mouse cursor
+ in windowed mode should work much better.
+ - [X11] Bugfix: Added a bunch of more keys that are recognized by
+ GLFW.
+ - [X11] Bugfix: glfwGetNumberOfProcessors now works for IRIX (earlier
+ versions of GLFW would not compile under IRIX).
+
+
+2.0.1
+
+ - glfwTerminate() will now be called automatically upon normal program
+ termination (using atexit())
+ - [Win32] Bugfix: Buffer-swapping did not work if a window lost
+ focus.
+ - [Win32] Bugfix: Top level Makefile did not work under Windows
+ 9x.
+ - [Win32] Bugfix: NULL declaration in glfw.h was not MSVC 7.x
+ compatible.
+ - [X11] Bugfix: GLFW would not build with C++ (e.g. g++).
+
+
+2.0
+
+ - GLFW is no longer a single source file, but an entire link library.
+ - Added multi threading support.
+ - Added more window control.
+ - New distribution layout (both Win32 and X11 version in same archive).
+ - Added GLFW Users Manual and GLFW Reference Manual as PDF files.
+ - Some bugfixes.
+
+
+1.0.2
+
+ - Improved fullscreen functionality.
+ - Added fullscreen support for X11.
+
+
+1.0.1
+
+ - Added support for the X Window System.
+ - Fixed bugs.
+
+
+1.0.0
+
+ - First release.
+ - Only supported Windows.
+
+
+
+
+6. Directory structure of the GLFW distribution
+
+Here is an overview of the directory structure of the GLFW distribution:
+
+
+
+
+ docs |
+ GLFW manuals in PDF format |
+
+
+ examples |
+ Several example programs in C |
+
+
+ include/GL |
+ The GLFW C/C++ header file |
+
+
+ lib |
+ The source code for GLFW |
+
+
+ lib/macosx
+ | Mac OS X-specific code |
+
+
+ lib/win32
+ | Windows-specific code |
+
+
+ lib/x11 |
+ Unix/X11-specific code |
+
+
+
+
+
+7. Contacting the project
+
+The official GLFW web site can be found here: http://glfw.sourceforge.net/. It
+contains the latest version of GLFW, news and other information that is useful
+for OpenGL development.
+
+If you have questions related to the use of GLFW, we have a user's web
+forum, and a user's mailing
+list on SF.net, and the IRC channel #glfw
on Freenode.
+
+If you have a bug to report or a feature you'd like to request, please file
+it in the SF.net
+trackers.
+
+Finally, if you're interested in helping out with the development of GLFW or
+porting it to your favorite platform, we have a developer's
+mailing list, or you could join us on #glfw
.
+
+
+
+8. Acknowledgements
+
+GLFW would not be what it is today without the help from:
+
+
+ - Marcus Geelnard, the original author and long-time maintainer of GLFW,
+ without whose brilliant work none of this would have happened.
+
+ - Robin Leffmann, for his work on Mac OS X and other platforms, and his
+ invaluable support.
+
+ - Keith Bauer, for his invaluable help with porting and maintaining GLFW on
+ Mac OS X, and for his many ideas.
+
+ - Ozzy @ Orkysquad,
+ for his dedication to GLFW, for debugging my source, and for his
+ valuable experience with game development.
+
+ - Jeff Molofee, the author of the excellent OpenGL tutorials at NeHe Productions.
+ Much of the Windows code of GLFW was originally based on Jeff's
+ code.
+
+ - Douglas C. Schmidt and Irfan Pyarali, for their excellent article Strategies for
+ Implementing POSIX Condition Variables on Win32, which was the basis for
+ the Win32 condition variable implementation in GLFW.
+
+ - Bobyshev Alexander and Martins Mozeiko, for the original proposal of
+ an FSAA hint and their work on the Win32 implementation of FSAA.
+
+ - Gerald Franz, who made GLFW compile under IRIX, and supplied patches
+ for the X11 keyboard translation routine.
+
+ - Bradley Smith, for his updates of the D support and his ports of the
+ remaining examples to the D language.
+
+ - Olivier Delannoy, for the initial implementation of FSAA support on
+ X11, cross-compiling support for MinGW and general extreme usefulness.
+
+ - Glenn Lewis, for helping out with support for the D programming
+ language.
+
+ - David Medlock, for doing the initial Lua port.
+
+ - Frank Wille, for helping me with the AmigaOS port and making GLFW
+ compile under IRIX 5.3.
+
+ - Matt Sealey, for helping me with the MorphOS port.
+
+ - Paul R. Deppe, who helped me with Cygwin support, and made an
+ adaption of PLIB
+ so that it can use GLFW (instead of GLUT).
+
+ - Jarrod Davis, for the Delphi port of GLFW.
+
+ - Toni Jovanoski, for helping me with the MASM32 port of GLFW, and
+ supplying the example program and fixed OpenGL and GLU bindings for
+ MASM32.
+
+ - Sebastian Schuberth, for the OpenWatcom makefiles.
+
+ - Dmitri Shuralyov, Samuli Tuomola, Santi Zupancic, Sylvain
+ Hellegouarch, and many others for support, bug reports and
+ testing.
+
+ - Дмитри Малышев, for the idea of a GLFW_NO_GLU macro.
+
+ - OpenGL.org, and all the people on
+ the discussion forums there that have provided help during the development of
+ GLFW.
+
+ - The MSDN Online Library,
+ which was used extensively for Windows development.
+
+ - All the feedback from the GLFW community - thank you!
+
+ - Everyone we forgot to thank - thank you!
+
+
+
+
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 00000000..2a915405
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,36 @@
+
+link_libraries(libglfwStatic ${GLFW_LIBRARIES} ${OPENGL_glu_LIBRARY})
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include ${OPENGL_INCLUDE_DIR})
+
+add_executable(defaults defaults.c)
+add_executable(events events.c)
+add_executable(joysticks joysticks.c)
+add_executable(peter peter.c)
+add_executable(reopen reopen.c)
+add_executable(version version.c)
+
+if(APPLE)
+ # Set fancy names for bundles
+ add_executable(Accuracy MACOSX_BUNDLE accuracy.c)
+ add_executable(FSAA MACOSX_BUNDLE fsaa.c)
+ add_executable(Tearing MACOSX_BUNDLE tearing.c)
+else()
+ # Set boring names for executables
+ add_executable(accuracy WIN32 accuracy.c)
+ add_executable(tearing WIN32 tearing.c)
+ add_executable(fsaa WIN32 fsaa.c)
+endif(APPLE)
+
+if(MSVC)
+ # Tell MSVC to use main instead of WinMain for Windows subsystem executables
+ set_target_properties(accuracy defaults events fsaa peter reopen tearing version PROPERTIES LINK_FLAGS "/ENTRY:mainCRTStartup")
+endif(MSVC)
+
+if(CYGWIN)
+ # Set cross-compile and subsystem compile and link flags
+ set_target_properties(accuracy defaults events fsaa joysticks peter reopen tearing version PROPERTIES COMPILE_FLAGS "-mno-cygwin")
+ set_target_properties(accuracy fsaa tearing PROPERTIES LINK_FLAGS "-mno-cygwin -mwindows")
+ set_target_properties(events defaults joysticks peter reopen version PROPERTIES LINK_FLAGS "-mno-cygwin -mconsole")
+endif(CYGWIN)
+
diff --git a/tests/accuracy.c b/tests/accuracy.c
new file mode 100644
index 00000000..3811cd81
--- /dev/null
+++ b/tests/accuracy.c
@@ -0,0 +1,103 @@
+//========================================================================
+// Mouse cursor accuracy test
+// Copyright (c) Camilla Berglund
+//
+// 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.
+//
+//========================================================================
+//
+// This test came about as the result of bug #1867804
+//
+// No sign of said bug has so far been detected
+//
+//========================================================================
+
+#include
+
+#include
+#include
+
+static int cursor_x = 0, cursor_y = 0;
+static int window_width = 640, window_height = 480;
+
+static void GLFWCALL window_size_callback(int width, int height)
+{
+ window_width = width;
+ window_height = height;
+
+ glViewport(0, 0, window_width, window_height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluOrtho2D(0.f, window_width, 0.f, window_height);
+}
+
+static void GLFWCALL mouse_position_callback(int x, int y)
+{
+ cursor_x = x;
+ cursor_y = y;
+}
+
+int main(void)
+{
+ if (!glfwInit())
+ {
+ fprintf(stderr, "Failed to initialize GLFW\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (!glfwOpenWindow(window_width, window_height, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
+ {
+ glfwTerminate();
+
+ fprintf(stderr, "Failed to open GLFW window\n");
+ exit(EXIT_FAILURE);
+ }
+
+ glfwSetWindowTitle("Cursor Inaccuracy Detector");
+ glfwSetMousePosCallback(mouse_position_callback);
+ glfwSetWindowSizeCallback(window_size_callback);
+ glfwSwapInterval(1);
+
+ glClearColor(0, 0, 0, 0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ while (glfwGetWindowParam(GLFW_OPENED))
+ {
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glColor3f(1.f, 1.f, 1.f);
+
+ glBegin(GL_LINES);
+ glVertex2f(0.f, (GLfloat) window_height - cursor_y);
+ glVertex2f((GLfloat) window_width, (GLfloat) window_height - cursor_y);
+ glVertex2f((GLfloat) cursor_x, 0.f);
+ glVertex2f((GLfloat) cursor_x, (GLfloat) window_height);
+ glEnd();
+
+ glfwSwapBuffers();
+ }
+
+ glfwTerminate();
+ exit(EXIT_SUCCESS);
+}
+
diff --git a/tests/defaults.c b/tests/defaults.c
new file mode 100644
index 00000000..58b77b4c
--- /dev/null
+++ b/tests/defaults.c
@@ -0,0 +1,98 @@
+//========================================================================
+// Default window/context test
+// Copyright (c) Camilla Berglund
+//
+// 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.
+//
+//========================================================================
+//
+// This test creates a windowed mode window with all parameters set to
+// default values and then reports the actual parameters of the created
+// window and context
+//
+//========================================================================
+
+#include
+
+#include
+#include
+
+typedef struct
+{
+ int param;
+ char* name;
+} Param;
+
+static Param parameters[] =
+{
+ { GLFW_ACCELERATED, "accelerated" },
+ { GLFW_RED_BITS, "red bits" },
+ { GLFW_GREEN_BITS, "green bits" },
+ { GLFW_BLUE_BITS, "blue bits" },
+ { GLFW_ALPHA_BITS, "alpha bits" },
+ { GLFW_DEPTH_BITS, "depth bits" },
+ { GLFW_STENCIL_BITS, "stencil bits" },
+ { GLFW_REFRESH_RATE, "refresh rate" },
+ { GLFW_ACCUM_RED_BITS, "accum red bits" },
+ { GLFW_ACCUM_GREEN_BITS, "accum green bits" },
+ { GLFW_ACCUM_BLUE_BITS, "accum blue bits" },
+ { GLFW_ACCUM_ALPHA_BITS, "accum alpha bits" },
+ { GLFW_AUX_BUFFERS, "aux buffers" },
+ { GLFW_STEREO, "stereo" },
+ { GLFW_FSAA_SAMPLES, "FSAA samples" },
+ { GLFW_OPENGL_VERSION_MAJOR, "OpenGL major" },
+ { GLFW_OPENGL_VERSION_MINOR, "OpenGL minor" },
+ { GLFW_OPENGL_FORWARD_COMPAT, "OpenGL forward compatible" },
+ { GLFW_OPENGL_DEBUG_CONTEXT, "OpenGL debug context" },
+ { GLFW_OPENGL_PROFILE, "OpenGL profile" },
+};
+
+int main(void)
+{
+ int i, width, height;
+
+ if (!glfwInit())
+ {
+ fprintf(stderr, "Failed to initialize GLFW\n");
+ exit(1);
+ }
+
+ if (!glfwOpenWindow(0, 0, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
+ {
+ glfwTerminate();
+
+ fprintf(stderr, "Failed to open GLFW default window\n");
+ exit(1);
+ }
+
+ glfwGetWindowSize(&width, &height);
+
+ printf("window size: %ix%i\n", width, height);
+
+ for (i = 0; (size_t) i < sizeof(parameters) / sizeof(parameters[0]); i++)
+ {
+ printf("%s: %i\n", parameters[i].name, glfwGetWindowParam(parameters[i].param));
+ }
+
+ glfwCloseWindow();
+ glfwTerminate();
+ exit(0);
+}
+
diff --git a/tests/events.c b/tests/events.c
new file mode 100644
index 00000000..0434844e
--- /dev/null
+++ b/tests/events.c
@@ -0,0 +1,309 @@
+//========================================================================
+// Event linter (event spewer)
+// Copyright (c) Camilla Berglund
+//
+// 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.
+//
+//========================================================================
+//
+// This test hooks every available callback and outputs their arguments
+//
+// Log messages go to stdout, error messages to stderr
+//
+// Every event also gets a (sequential) number to aid discussion of logs
+//
+//========================================================================
+
+#include
+
+#include
+#include
+#include
+#include
+
+static GLboolean keyrepeat = 0;
+static GLboolean systemkeys = 1;
+static unsigned int counter = 0;
+
+static const char* get_key_name(int key)
+{
+ switch (key)
+ {
+ case GLFW_KEY_UNKNOWN: return "unknown";
+ case GLFW_KEY_SPACE: return "space";
+ case GLFW_KEY_ESC: return "escape";
+ case GLFW_KEY_F1: return "F1";
+ case GLFW_KEY_F2: return "F2";
+ case GLFW_KEY_F3: return "F3";
+ case GLFW_KEY_F4: return "F4";
+ case GLFW_KEY_F5: return "F5";
+ case GLFW_KEY_F6: return "F6";
+ case GLFW_KEY_F7: return "F7";
+ case GLFW_KEY_F8: return "F8";
+ case GLFW_KEY_F9: return "F9";
+ case GLFW_KEY_F10: return "F10";
+ case GLFW_KEY_F11: return "F11";
+ case GLFW_KEY_F12: return "F12";
+ case GLFW_KEY_F13: return "F13";
+ case GLFW_KEY_F14: return "F14";
+ case GLFW_KEY_F15: return "F15";
+ case GLFW_KEY_F16: return "F16";
+ case GLFW_KEY_F17: return "F17";
+ case GLFW_KEY_F18: return "F18";
+ case GLFW_KEY_F19: return "F19";
+ case GLFW_KEY_F20: return "F20";
+ case GLFW_KEY_F21: return "F21";
+ case GLFW_KEY_F22: return "F22";
+ case GLFW_KEY_F23: return "F23";
+ case GLFW_KEY_F24: return "F24";
+ case GLFW_KEY_F25: return "F25";
+ case GLFW_KEY_UP: return "up";
+ case GLFW_KEY_DOWN: return "down";
+ case GLFW_KEY_LEFT: return "left";
+ case GLFW_KEY_RIGHT: return "right";
+ case GLFW_KEY_LSHIFT: return "left shift";
+ case GLFW_KEY_RSHIFT: return "right shift";
+ case GLFW_KEY_LCTRL: return "left control";
+ case GLFW_KEY_RCTRL: return "right control";
+ case GLFW_KEY_LALT: return "left alt";
+ case GLFW_KEY_RALT: return "right alt";
+ case GLFW_KEY_TAB: return "tab";
+ case GLFW_KEY_ENTER: return "enter";
+ case GLFW_KEY_BACKSPACE: return "backspace";
+ case GLFW_KEY_INSERT: return "insert";
+ case GLFW_KEY_DEL: return "delete";
+ case GLFW_KEY_PAGEUP: return "page up";
+ case GLFW_KEY_PAGEDOWN: return "page down";
+ case GLFW_KEY_HOME: return "home";
+ case GLFW_KEY_END: return "end";
+ case GLFW_KEY_KP_0: return "keypad 0";
+ case GLFW_KEY_KP_1: return "keypad 1";
+ case GLFW_KEY_KP_2: return "keypad 2";
+ case GLFW_KEY_KP_3: return "keypad 3";
+ case GLFW_KEY_KP_4: return "keypad 4";
+ case GLFW_KEY_KP_5: return "keypad 5";
+ case GLFW_KEY_KP_6: return "keypad 6";
+ case GLFW_KEY_KP_7: return "keypad 7";
+ case GLFW_KEY_KP_8: return "keypad 8";
+ case GLFW_KEY_KP_9: return "keypad 9";
+ case GLFW_KEY_KP_DIVIDE: return "keypad divide";
+ case GLFW_KEY_KP_MULTIPLY: return "keypad multiply";
+ case GLFW_KEY_KP_SUBTRACT: return "keypad subtract";
+ case GLFW_KEY_KP_ADD: return "keypad add";
+ case GLFW_KEY_KP_DECIMAL: return "keypad decimal";
+ case GLFW_KEY_KP_EQUAL: return "keypad equal";
+ case GLFW_KEY_KP_ENTER: return "keypad enter";
+ case GLFW_KEY_KP_NUM_LOCK: return "keypad num lock";
+ case GLFW_KEY_CAPS_LOCK: return "caps lock";
+ case GLFW_KEY_SCROLL_LOCK: return "scroll lock";
+ case GLFW_KEY_PAUSE: return "pause";
+ case GLFW_KEY_LSUPER: return "left super";
+ case GLFW_KEY_RSUPER: return "right super";
+ case GLFW_KEY_MENU: return "menu";
+ }
+
+ return NULL;
+}
+
+static const char* get_action_name(int action)
+{
+ switch (action)
+ {
+ case GLFW_PRESS:
+ return "was pressed";
+ case GLFW_RELEASE:
+ return "was released";
+ }
+
+ return "caused unknown action";
+}
+
+static const char* get_button_name(int button)
+{
+ switch (button)
+ {
+ case GLFW_MOUSE_BUTTON_LEFT:
+ return "left";
+ case GLFW_MOUSE_BUTTON_RIGHT:
+ return "right";
+ case GLFW_MOUSE_BUTTON_MIDDLE:
+ return "middle";
+ }
+
+ return NULL;
+}
+
+static const char* get_character_string(int character)
+{
+ static char result[6 + 1];
+
+ int length = wctomb(result, character);
+ if (length == -1)
+ length = 0;
+
+ result[length] = '\0';
+ return result;
+}
+
+static void GLFWCALL window_size_callback(int width, int height)
+{
+ printf("%08x at %0.3f: Window size: %i %i\n",
+ counter++,
+ glfwGetTime(),
+ width,
+ height);
+
+ glViewport(0, 0, width, height);
+}
+
+static int GLFWCALL window_close_callback(void)
+{
+ printf("%08x at %0.3f: Window close\n", counter++, glfwGetTime());
+ return 1;
+}
+
+static void GLFWCALL window_refresh_callback(void)
+{
+ printf("%08x at %0.3f: Window refresh\n", counter++, glfwGetTime());
+}
+
+static void GLFWCALL mouse_button_callback(int button, int action)
+{
+ const char* name = get_button_name(button);
+
+ printf("%08x at %0.3f: Mouse button %i", counter++, glfwGetTime(), button);
+
+ if (name)
+ printf(" (%s) was %s\n", name, get_action_name(action));
+ else
+ printf(" was %s\n", get_action_name(action));
+}
+
+static void GLFWCALL mouse_position_callback(int x, int y)
+{
+ printf("%08x at %0.3f: Mouse position: %i %i\n", counter++, glfwGetTime(), x, y);
+}
+
+static void GLFWCALL mouse_wheel_callback(int position)
+{
+ printf("%08x at %0.3f: Mouse wheel: %i\n", counter++, glfwGetTime(), position);
+}
+
+static void GLFWCALL key_callback(int key, int action)
+{
+ const char* name = get_key_name(key);
+
+ printf("%08x at %0.3f: Key 0x%04x", counter++, glfwGetTime(), key);
+
+ if (name)
+ printf(" (%s) was %s\n", name, get_action_name(action));
+ else if (isgraph(key))
+ printf(" (%c) was %s\n", key, get_action_name(action));
+ else
+ printf(" was %s\n", get_action_name(action));
+
+ if (action != GLFW_PRESS)
+ return;
+
+ switch (key)
+ {
+ case 'R':
+ {
+ keyrepeat = !keyrepeat;
+ if (keyrepeat)
+ glfwEnable(GLFW_KEY_REPEAT);
+ else
+ glfwDisable(GLFW_KEY_REPEAT);
+
+ printf("(( key repeat %s ))\n", keyrepeat ? "enabled" : "disabled");
+ break;
+ }
+
+ case 'S':
+ {
+ systemkeys = !systemkeys;
+ if( systemkeys )
+ glfwEnable(GLFW_SYSTEM_KEYS);
+ else
+ glfwDisable(GLFW_SYSTEM_KEYS);
+
+ printf("(( system keys %s ))\n", systemkeys ? "enabled" : "disabled");
+ break;
+ }
+ }
+}
+
+static void GLFWCALL char_callback(int character, int action)
+{
+ printf("%08x at %0.3f: Character 0x%04x", counter++, glfwGetTime(), character);
+
+ printf(" (%s) %s\n", get_character_string(character), get_action_name(action));
+}
+
+int main(void)
+{
+ setlocale(LC_ALL, "");
+
+ if (!glfwInit())
+ {
+ fprintf(stderr, "Failed to initialize GLFW\n");
+ exit(1);
+ }
+
+ printf("Library initialized\n");
+
+ if (!glfwOpenWindow(0, 0, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
+ {
+ glfwTerminate();
+
+ fprintf(stderr, "Failed to create GLFW window");
+ exit(1);
+ }
+
+ printf("Window opened\n");
+
+ glfwSetWindowTitle("Event Linter");
+ glfwSwapInterval(1);
+
+ glfwSetWindowSizeCallback(window_size_callback);
+ glfwSetWindowCloseCallback(window_close_callback);
+ glfwSetWindowRefreshCallback(window_refresh_callback);
+ glfwSetMouseButtonCallback(mouse_button_callback);
+ glfwSetMousePosCallback(mouse_position_callback);
+ glfwSetMouseWheelCallback(mouse_wheel_callback);
+ glfwSetKeyCallback(key_callback);
+ glfwSetCharCallback(char_callback);
+
+ printf("Key repeat should be %s\n", keyrepeat ? "enabled" : "disabled");
+ printf("System keys should be %s\n", systemkeys ? "enabled" : "disabled");
+
+ printf("Main loop starting\n");
+
+ while (glfwGetWindowParam(GLFW_OPENED) == GL_TRUE)
+ {
+ glfwWaitEvents();
+ glClear(GL_COLOR_BUFFER_BIT);
+ glfwSwapBuffers();
+ }
+
+ glfwTerminate();
+ exit(0);
+}
+
diff --git a/tests/fsaa.c b/tests/fsaa.c
new file mode 100644
index 00000000..91c66d91
--- /dev/null
+++ b/tests/fsaa.c
@@ -0,0 +1,105 @@
+//========================================================================
+// Fullscreen multisampling anti-aliasing test
+// Copyright (c) Camilla Berglund
+//
+// 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.
+//
+//========================================================================
+//
+// This test renders two high contrast, slowly rotating quads, one aliased
+// and one (hopefully) anti-aliased, thus allowing for visual verification
+// of whether FSAA is indeed enabled
+//
+//========================================================================
+
+#include
+
+#include
+#include
+
+#ifndef GL_ARB_multisample
+#define GL_MULTISAMPLE_ARB 0x809D
+#endif
+
+static void GLFWCALL window_size_callback(int width, int height)
+{
+ glViewport(0, 0, width, height);
+}
+
+int main(void)
+{
+ if (!glfwInit())
+ {
+ fprintf(stderr, "Failed to initialize GLFW\n");
+ exit(EXIT_FAILURE);
+ }
+
+ glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 4);
+
+ if (!glfwOpenWindow(400, 400, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
+ {
+ glfwTerminate();
+
+ fprintf(stderr, "Failed to open GLFW window\n");
+ exit(EXIT_FAILURE);
+ }
+
+ glfwSetWindowTitle("Aliasing Detector");
+ glfwSetWindowSizeCallback(window_size_callback);
+ glfwSwapInterval(1);
+
+ int samples = glfwGetWindowParam(GLFW_FSAA_SAMPLES);
+ if (samples)
+ printf("Context reports FSAA is supported with %i samples\n", samples);
+ else
+ printf("Context reports FSAA is unsupported\n");
+
+ glMatrixMode(GL_PROJECTION);
+ gluOrtho2D(0.f, 1.f, 0.f, 1.f);
+
+ while (glfwGetWindowParam(GLFW_OPENED))
+ {
+ GLfloat time = (GLfloat) glfwGetTime();
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glLoadIdentity();
+ glTranslatef(0.5f, 0.f, 0.f);
+ glRotatef(time, 0.f, 0.f, 1.f);
+
+ glEnable(GL_MULTISAMPLE_ARB);
+ glColor3f(1.f, 1.f, 1.f);
+ glRectf(-0.25f, -0.25f, 0.25f, 0.25f);
+
+ glLoadIdentity();
+ glTranslatef(-0.5f, 0.f, 0.f);
+ glRotatef(time, 0.f, 0.f, 1.f);
+
+ glDisable(GL_MULTISAMPLE_ARB);
+ glColor3f(1.f, 1.f, 1.f);
+ glRectf(-0.25f, -0.25f, 0.25f, 0.25f);
+
+ glfwSwapBuffers();
+ }
+
+ glfwTerminate();
+ exit(EXIT_SUCCESS);
+}
+
diff --git a/tests/getopt.c b/tests/getopt.c
new file mode 100644
index 00000000..b891b0a5
--- /dev/null
+++ b/tests/getopt.c
@@ -0,0 +1,253 @@
+/*****************************************************************************
+* getopt.c - competent and free getopt library.
+* $Header: /cvsroot/freegetopt/freegetopt/getopt.c,v 1.2 2003/10/26 03:10:20 vindaci Exp $
+*
+* Copyright (c)2002-2003 Mark K. Kim
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in
+* the documentation and/or other materials provided with the
+* distribution.
+*
+* * Neither the original author of this software nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+* DAMAGE.
+*/
+#include
+#include
+#include
+#include "getopt.h"
+
+
+/* 2009-10-12 Camilla Berglund
+ *
+ * Removed unused global static variable 'ID'.
+ */
+
+
+char* optarg = NULL;
+int optind = 0;
+int opterr = 1;
+int optopt = '?';
+
+
+static char** prev_argv = NULL; /* Keep a copy of argv and argc to */
+static int prev_argc = 0; /* tell if getopt params change */
+static int argv_index = 0; /* Option we're checking */
+static int argv_index2 = 0; /* Option argument we're checking */
+static int opt_offset = 0; /* Index into compounded "-option" */
+static int dashdash = 0; /* True if "--" option reached */
+static int nonopt = 0; /* How many nonopts we've found */
+
+static void increment_index()
+{
+ /* Move onto the next option */
+ if(argv_index < argv_index2)
+ {
+ while(prev_argv[++argv_index] && prev_argv[argv_index][0] != '-'
+ && argv_index < argv_index2+1);
+ }
+ else argv_index++;
+ opt_offset = 1;
+}
+
+
+/*
+* Permutes argv[] so that the argument currently being processed is moved
+* to the end.
+*/
+static int permute_argv_once()
+{
+ /* Movability check */
+ if(argv_index + nonopt >= prev_argc) return 1;
+ /* Move the current option to the end, bring the others to front */
+ else
+ {
+ char* tmp = prev_argv[argv_index];
+
+ /* Move the data */
+ memmove(&prev_argv[argv_index], &prev_argv[argv_index+1],
+ sizeof(char**) * (prev_argc - argv_index - 1));
+ prev_argv[prev_argc - 1] = tmp;
+
+ nonopt++;
+ return 0;
+ }
+}
+
+
+int getopt(int argc, char** argv, char* optstr)
+{
+ int c = 0;
+
+ /* If we have new argv, reinitialize */
+ if(prev_argv != argv || prev_argc != argc)
+ {
+ /* Initialize variables */
+ prev_argv = argv;
+ prev_argc = argc;
+ argv_index = 1;
+ argv_index2 = 1;
+ opt_offset = 1;
+ dashdash = 0;
+ nonopt = 0;
+ }
+
+ /* Jump point in case we want to ignore the current argv_index */
+ getopt_top:
+
+ /* Misc. initializations */
+ optarg = NULL;
+
+ /* Dash-dash check */
+ if(argv[argv_index] && !strcmp(argv[argv_index], "--"))
+ {
+ dashdash = 1;
+ increment_index();
+ }
+
+ /* If we're at the end of argv, that's it. */
+ if(argv[argv_index] == NULL)
+ {
+ c = -1;
+ }
+ /* Are we looking at a string? Single dash is also a string */
+ else if(dashdash || argv[argv_index][0] != '-' || !strcmp(argv[argv_index], "-"))
+ {
+ /* If we want a string... */
+ if(optstr[0] == '-')
+ {
+ c = 1;
+ optarg = argv[argv_index];
+ increment_index();
+ }
+ /* If we really don't want it (we're in POSIX mode), we're done */
+ else if(optstr[0] == '+' || getenv("POSIXLY_CORRECT"))
+ {
+ c = -1;
+
+ /* Everything else is a non-opt argument */
+ nonopt = argc - argv_index;
+ }
+ /* If we mildly don't want it, then move it back */
+ else
+ {
+ if(!permute_argv_once()) goto getopt_top;
+ else c = -1;
+ }
+ }
+ /* Otherwise we're looking at an option */
+ else
+ {
+ char* opt_ptr = NULL;
+
+ /* Grab the option */
+ c = argv[argv_index][opt_offset++];
+
+ /* Is the option in the optstr? */
+ if(optstr[0] == '-') opt_ptr = strchr(optstr+1, c);
+ else opt_ptr = strchr(optstr, c);
+ /* Invalid argument */
+ if(!opt_ptr)
+ {
+ if(opterr)
+ {
+ fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c);
+ }
+
+ optopt = c;
+ c = '?';
+
+ /* Move onto the next option */
+ increment_index();
+ }
+ /* Option takes argument */
+ else if(opt_ptr[1] == ':')
+ {
+ /* ie, -oARGUMENT, -xxxoARGUMENT, etc. */
+ if(argv[argv_index][opt_offset] != '\0')
+ {
+ optarg = &argv[argv_index][opt_offset];
+ increment_index();
+ }
+ /* ie, -o ARGUMENT (only if it's a required argument) */
+ else if(opt_ptr[2] != ':')
+ {
+ /* One of those "you're not expected to understand this" moment */
+ if(argv_index2 < argv_index) argv_index2 = argv_index;
+ while(argv[++argv_index2] && argv[argv_index2][0] == '-');
+ optarg = argv[argv_index2];
+
+ /* Don't cross into the non-option argument list */
+ if(argv_index2 + nonopt >= prev_argc) optarg = NULL;
+
+ /* Move onto the next option */
+ increment_index();
+ }
+ else
+ {
+ /* Move onto the next option */
+ increment_index();
+ }
+
+ /* In case we got no argument for an option with required argument */
+ if(optarg == NULL && opt_ptr[2] != ':')
+ {
+ optopt = c;
+ c = '?';
+
+ if(opterr)
+ {
+ fprintf(stderr,"%s: option requires an argument -- %c\n",
+ argv[0], optopt);
+ }
+ }
+ }
+ /* Option does not take argument */
+ else
+ {
+ /* Next argv_index */
+ if(argv[argv_index][opt_offset] == '\0')
+ {
+ increment_index();
+ }
+ }
+ }
+
+ /* Calculate optind */
+ if(c == -1)
+ {
+ optind = argc - nonopt;
+ }
+ else
+ {
+ optind = argv_index;
+ }
+
+ return c;
+}
+
+
+/* vim:ts=3
+*/
diff --git a/tests/getopt.h b/tests/getopt.h
new file mode 100644
index 00000000..0b78650a
--- /dev/null
+++ b/tests/getopt.h
@@ -0,0 +1,63 @@
+/*****************************************************************************
+* getopt.h - competent and free getopt library.
+* $Header: /cvsroot/freegetopt/freegetopt/getopt.h,v 1.2 2003/10/26 03:10:20 vindaci Exp $
+*
+* Copyright (c)2002-2003 Mark K. Kim
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in
+* the documentation and/or other materials provided with the
+* distribution.
+*
+* * Neither the original author of this software nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+* DAMAGE.
+*/
+#ifndef GETOPT_H_
+#define GETOPT_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+extern char* optarg;
+extern int optind;
+extern int opterr;
+extern int optopt;
+
+int getopt(int argc, char** argv, char* optstr);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* GETOPT_H_ */
+
+
+/* vim:ts=3
+*/
diff --git a/tests/iconify.c b/tests/iconify.c
new file mode 100644
index 00000000..14c6e726
--- /dev/null
+++ b/tests/iconify.c
@@ -0,0 +1,158 @@
+//========================================================================
+// Iconify/restore test program
+// Copyright (c) Camilla Berglund
+//
+// 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.
+//
+//========================================================================
+//
+// This program is used to test the iconify/restore functionality for
+// both fullscreen and windowed mode windows
+//
+//========================================================================
+
+#include
+
+#include
+#include
+
+#include "getopt.h"
+
+static void usage(void)
+{
+ printf("iconify [-h] [-f]\n");
+}
+
+static void GLFWCALL key_callback(int key, int action)
+{
+ printf("%0.2f Key %s\n",
+ glfwGetTime(),
+ action == GLFW_PRESS ? "pressed" : "released");
+
+ if (action != GLFW_PRESS)
+ return;
+
+ switch (key)
+ {
+ case GLFW_KEY_SPACE:
+ glfwIconifyWindow();
+ break;
+ case GLFW_KEY_ESC:
+ glfwCloseWindow();
+ break;
+ }
+}
+
+static void GLFWCALL size_callback(int width, int height)
+{
+ glViewport(0, 0, width, height);
+}
+
+int main(int argc, char** argv)
+{
+ int width, height, ch;
+ int mode = GLFW_WINDOW;
+ GLboolean active = -1, iconified = -1;
+
+ while ((ch = getopt(argc, argv, "fh")) != -1)
+ {
+ switch (ch)
+ {
+ case 'h':
+ usage();
+ exit(EXIT_SUCCESS);
+
+ case 'f':
+ mode = GLFW_FULLSCREEN;
+ break;
+
+ default:
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (!glfwInit())
+ {
+ fprintf(stderr, "Failed to initialize GLFW\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (mode == GLFW_FULLSCREEN)
+ {
+ GLFWvidmode mode;
+ glfwGetDesktopMode(&mode);
+ width = mode.Width;
+ height = mode.Height;
+ }
+ else
+ {
+ width = 0;
+ height = 0;
+ }
+
+ if (!glfwOpenWindow(width, height, 0, 0, 0, 0, 0, 0, mode))
+ {
+ glfwTerminate();
+
+ fprintf(stderr, "Failed to open GLFW window\n");
+ exit(EXIT_FAILURE);
+ }
+
+ glfwSetWindowTitle("Iconify");
+ glfwSwapInterval(1);
+ glfwSetKeyCallback(key_callback);
+ glfwSetWindowSizeCallback(size_callback);
+
+ glEnable(GL_SCISSOR_TEST);
+
+ while (glfwGetWindowParam(GLFW_OPENED))
+ {
+ int width, height;
+
+ if (iconified != glfwGetWindowParam(GLFW_ICONIFIED) ||
+ active != glfwGetWindowParam(GLFW_ACTIVE))
+ {
+ iconified = glfwGetWindowParam(GLFW_ICONIFIED);
+ active = glfwGetWindowParam(GLFW_ACTIVE);
+
+ printf("%0.2f %s %s\n",
+ glfwGetTime(),
+ iconified ? "Iconified" : "Restored",
+ active ? "Active" : "Inactive");
+ }
+
+ glfwGetWindowSize(&width, &height);
+
+ glScissor(0, 0, width, height);
+ glClearColor(0, 0, 0, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glScissor(0, 0, 640, 480);
+ glClearColor(1, 1, 1, 0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glfwSwapBuffers();
+ }
+
+ glfwTerminate();
+ exit(EXIT_SUCCESS);
+}
+
diff --git a/tests/joysticks.c b/tests/joysticks.c
new file mode 100644
index 00000000..7015e131
--- /dev/null
+++ b/tests/joysticks.c
@@ -0,0 +1,136 @@
+/*========================================================================
+ * This is a small test application for GLFW.
+ * joystick input test.
+ *========================================================================*/
+
+#include
+
+#include
+#include
+
+#define MAX_AXES 10
+#define MAX_BUTTONS 30
+
+struct JoystickState
+{
+ int present;
+ int num_axes;
+ int num_buttons;
+ float axes[MAX_AXES];
+ unsigned char buttons[MAX_BUTTONS];
+};
+
+static struct JoystickState states[GLFW_JOYSTICK_LAST + 1];
+
+int running;
+int keyrepeat = 0;
+int systemkeys = 1;
+
+
+/*========================================================================
+ * Retrieve joystick states
+ *========================================================================*/
+static void updateJoysticksState(void)
+{
+ int joy;
+
+ for (joy = GLFW_JOYSTICK_1; joy < GLFW_JOYSTICK_LAST + 1; joy++)
+ {
+ printf("Updating information for joystick %d\n", joy);
+ states[joy].present = glfwGetJoystickParam(joy, GLFW_PRESENT);
+ if (states[joy].present == GL_TRUE)
+ {
+ states[joy].num_axes = glfwGetJoystickPos(joy, states[joy].axes, MAX_AXES);
+ states[joy].num_buttons = glfwGetJoystickButtons(joy, states[joy].buttons, MAX_BUTTONS);
+ }
+ }
+}
+
+/*========================================================================
+ * Print out the state of all joysticks on the standard output
+ *========================================================================*/
+static void displayJoysticksState(void)
+{
+ int joy;
+ int i;
+
+ for (joy = GLFW_JOYSTICK_1; joy < GLFW_JOYSTICK_LAST + 1; joy++)
+ {
+ printf("Joystick %d: %s\n", joy, (states[joy].present == GL_TRUE ? "present" : "not connected"));
+
+ if (states[joy].present == GL_TRUE)
+ {
+ if (states[joy].num_axes > 0)
+ {
+ printf(" axes: %.3f", states[joy].axes[0]);
+ for (i = 1; i < states[joy].num_axes; i++)
+ printf(", %.3f", states[joy].axes[i]);
+
+ printf("\n");
+ }
+ else
+ printf(" axes: none\n");
+
+ if (states[joy].num_buttons > 0)
+ {
+ printf(" buttons: 00 => %c", ((states[joy].buttons[0] == GLFW_PRESS) ? 'P' : 'R'));
+
+ for (i = 1; i < states[joy].num_buttons; i++)
+ printf(", %02d => %c", i, ((states[joy].buttons[i] == GLFW_PRESS) ? 'P' : 'R'));
+
+ printf("\n");
+ }
+ else
+ printf(" buttons: none\n");
+ }
+ }
+}
+
+int main(void)
+{
+ double start;
+ double t;
+ double update;
+
+ /* Initialise GLFW */
+ glfwInit();
+ printf("The program will work for 20 seconds and display every seconds the state of the joysticks\n");
+ printf("Your computer is going to be very slow as the program is doing an active loop .....\n");
+
+ start = glfwGetTime();
+ update = start;
+
+ /* print the initial state of all joysticks */
+ updateJoysticksState();
+ printf("\n");
+ displayJoysticksState();
+
+ running = GL_TRUE;
+
+ /* Main loop */
+ while (running)
+ {
+ /* Get time */
+ t = glfwGetTime();
+
+ /* Display the state of all connected joysticks every secons */
+ if ((t - update) > 1.0)
+ {
+ update = t;
+ printf("\n");
+ updateJoysticksState();
+ printf("\n");
+ displayJoysticksState();
+ }
+
+ /* Check if the window was closed */
+ if ((t - start) > 20.0)
+ running = GL_FALSE;
+ }
+
+ /* Close OpenGL window and terminate GLFW */
+ glfwTerminate();
+
+ return 0;
+}
+
diff --git a/tests/peter.c b/tests/peter.c
new file mode 100644
index 00000000..4d516614
--- /dev/null
+++ b/tests/peter.c
@@ -0,0 +1,137 @@
+//========================================================================
+// Mouse cursor bug test
+// Copyright (c) Camilla Berglund
+//
+// 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.
+//
+//========================================================================
+//
+// This test came about as the result of bugs #1262764, #1726540 and
+// #1726592, all reported by the user peterpp, hence the name
+//
+// The utility of this test outside of these bugs is uncertain
+//
+//========================================================================
+
+#include
+
+#include
+#include
+
+static GLboolean cursor_enabled = GL_TRUE;
+
+static GLboolean open_window(void);
+
+static void toggle_mouse_cursor(void)
+{
+ if (cursor_enabled)
+ glfwDisable(GLFW_MOUSE_CURSOR);
+ else
+ glfwEnable(GLFW_MOUSE_CURSOR);
+
+ cursor_enabled = !cursor_enabled;
+}
+
+static void GLFWCALL mouse_position_callback(int x, int y)
+{
+ printf("Mouse moved to: %i %i\n", x, y);
+}
+
+static void GLFWCALL key_callback(int key, int action)
+{
+ switch (key)
+ {
+ case GLFW_KEY_SPACE:
+ {
+ if (action == GLFW_PRESS)
+ toggle_mouse_cursor();
+
+ break;
+ }
+
+ case 'R':
+ {
+ if (action == GLFW_PRESS)
+ {
+ glfwCloseWindow();
+ open_window();
+ }
+
+ break;
+ }
+ }
+}
+
+static void GLFWCALL window_size_callback(int width, int height)
+{
+ glViewport(0, 0, width, height);
+}
+
+static GLboolean open_window(void)
+{
+ int x, y;
+
+ if (!glfwOpenWindow(0, 0, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
+ return GL_FALSE;
+
+ glfwSetWindowTitle("Peter Detector");
+
+ glfwGetMousePos(&x, &y);
+ printf("Mouse position: %i %i\n", x, y);
+
+ glfwDisable(GLFW_AUTO_POLL_EVENTS);
+ glfwSetWindowSizeCallback(window_size_callback);
+ glfwSetMousePosCallback(mouse_position_callback);
+ glfwSetKeyCallback(key_callback);
+ glfwSwapInterval(1);
+
+ return GL_TRUE;
+}
+
+int main(void)
+{
+ if (!glfwInit())
+ {
+ fprintf(stderr, "Failed to initialize GLFW\n");
+ exit(1);
+ }
+
+ if (!open_window())
+ {
+ glfwTerminate();
+
+ fprintf(stderr, "Failed to open GLFW window\n");
+ exit(1);
+ }
+
+ glClearColor(0.f, 0.f, 0.f, 0.f);
+
+ while (glfwGetWindowParam(GLFW_OPENED))
+ {
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glfwSwapBuffers();
+ glfwWaitEvents();
+ }
+
+ glfwTerminate();
+ exit(0);
+}
+
diff --git a/tests/reopen.c b/tests/reopen.c
new file mode 100644
index 00000000..bfdda374
--- /dev/null
+++ b/tests/reopen.c
@@ -0,0 +1,170 @@
+//========================================================================
+// Window re-opener (open/close stress test)
+// Copyright (c) Camilla Berglund
+//
+// 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.
+//
+//========================================================================
+//
+// This test came about as the result of bug #1262773
+//
+// It closes and re-opens the GLFW window every five seconds, alternating
+// between windowed and fullscreen mode
+//
+// It also times and logs opening and closing actions and attempts to separate
+// user initiated window closing from its own
+//
+//========================================================================
+
+#include
+
+#include
+#include
+
+static GLboolean closed = GL_FALSE;
+
+static const char* get_mode_name(int mode)
+{
+ switch (mode)
+ {
+ case GLFW_WINDOW:
+ return "windowed";
+ case GLFW_FULLSCREEN:
+ return "fullscreen";
+ default:
+ return "unknown";
+ }
+}
+
+static void GLFWCALL window_size_callback(int width, int height)
+{
+ glViewport(0, 0, width, height);
+}
+
+static int GLFWCALL window_close_callback(void)
+{
+ printf("Close callback triggered\n");
+ closed = GL_TRUE;
+ return 0;
+}
+
+static void GLFWCALL key_callback(int key, int action)
+{
+ if (action != GLFW_PRESS)
+ return;
+
+ switch (key)
+ {
+ case 'Q':
+ case GLFW_KEY_ESC:
+ closed = GL_TRUE;
+ break;
+ }
+}
+
+static int open_window(int width, int height, int mode)
+{
+ double base = glfwGetTime();
+
+ if (!glfwOpenWindow(width, height, 0, 0, 0, 0, 16, 0, mode))
+ {
+ fprintf(stderr, "Failed to create %s mode GLFW window\n", get_mode_name(mode));
+ return 0;
+ }
+
+ glfwSetWindowTitle("Window Re-opener");
+ glfwSetWindowSizeCallback(window_size_callback);
+ glfwSetWindowCloseCallback(window_close_callback);
+ glfwSetKeyCallback(key_callback);
+ glfwSwapInterval(1);
+
+ printf("Opening %s mode window took %0.3f seconds\n",
+ get_mode_name(mode),
+ glfwGetTime() - base);
+
+ return 1;
+}
+
+static void close_window(void)
+{
+ double base = glfwGetTime();
+
+ glfwCloseWindow();
+
+ printf("Closing window took %0.3f seconds\n", glfwGetTime() - base);
+}
+
+int main(int argc, char** argv)
+{
+ int count = 0;
+
+ if (!glfwInit())
+ {
+ fprintf(stderr, "Failed to initialize GLFW\n");
+ exit(1);
+ }
+
+ for (;;)
+ {
+ if (!open_window(640, 480, (count & 1) ? GLFW_FULLSCREEN : GLFW_WINDOW))
+ {
+ glfwTerminate();
+ exit(1);
+ }
+
+ glMatrixMode(GL_PROJECTION);
+ glOrtho(-1.f, 1.f, -1.f, 1.f, 1.f, -1.f);
+ glMatrixMode(GL_MODELVIEW);
+
+ glClearColor(0.f, 0.f, 0.f, 0.f);
+ glColor3f(1.f, 1.f, 1.f);
+
+ glfwSetTime(0.0);
+
+ while (glfwGetTime() < 5.0)
+ {
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glPushMatrix();
+ glRotatef((GLfloat) glfwGetTime() * 100.f, 0.f, 0.f, 1.f);
+ glRectf(-0.5f, -0.5f, 1.f, 1.f);
+ glPopMatrix();
+
+ glfwSwapBuffers();
+
+ if (closed)
+ close_window();
+
+ if (!glfwGetWindowParam(GLFW_OPENED))
+ {
+ printf("User closed window\n");
+
+ glfwTerminate();
+ exit(0);
+ }
+ }
+
+ printf("Closing window\n");
+ close_window();
+
+ count++;
+ }
+}
+
diff --git a/tests/tearing.c b/tests/tearing.c
new file mode 100644
index 00000000..8e9f06a1
--- /dev/null
+++ b/tests/tearing.c
@@ -0,0 +1,84 @@
+//========================================================================
+// Vsync enabling test
+// Copyright (c) Camilla Berglund
+//
+// 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.
+//
+//========================================================================
+//
+// This test renders a high contrast, horizontally moving bar, allowing for
+// visual verification of whether the set swap interval is indeed obeyed
+//
+//========================================================================
+
+#include
+
+#include
+#include
+#include
+
+static void GLFWCALL window_size_callback(int width, int height)
+{
+ glViewport(0, 0, width, height);
+}
+
+int main(void)
+{
+ float position;
+
+ if (!glfwInit())
+ {
+ fprintf(stderr, "Failed to initialize GLFW\n");
+ exit(1);
+ }
+
+ if (!glfwOpenWindow(0, 0, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
+ {
+ glfwTerminate();
+
+ fprintf(stderr, "Failed to open GLFW window\n");
+ exit(1);
+ }
+
+ glfwSetWindowTitle("Tearing Detector");
+ glfwSetWindowSizeCallback(window_size_callback);
+ glfwSwapInterval(1);
+
+ glClearColor(0.f, 0.f, 0.f, 0.f);
+ glColor3f(1.f, 1.f, 1.f);
+
+ glMatrixMode(GL_PROJECTION);
+ glOrtho(-1.f, 1.f, -1.f, 1.f, 1.f, -1.f);
+ glMatrixMode(GL_MODELVIEW);
+
+ while (glfwGetWindowParam(GLFW_OPENED) == GL_TRUE)
+ {
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ position = cosf(glfwGetTime() * 4.f) * 0.75f;
+ glRectf(position - 0.25f, -1.f, position + 0.25f, 1.f);
+
+ glfwSwapBuffers();
+ }
+
+ glfwTerminate();
+ exit(0);
+}
+
diff --git a/tests/version.c b/tests/version.c
new file mode 100644
index 00000000..28f41b76
--- /dev/null
+++ b/tests/version.c
@@ -0,0 +1,253 @@
+//========================================================================
+// Version information dumper
+// Copyright (c) Camilla Berglund
+//
+// 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.
+//
+//========================================================================
+//
+// This test is a pale imitation of glxinfo(1), except not really
+//
+// It dumps GLFW and OpenGL version information
+//
+//========================================================================
+
+#include
+
+#ifndef GL_VERSION_3_2
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x0001
+#endif
+
+typedef const GLubyte * (APIENTRY *PFNGLGETSTRINGI) (GLenum, GLuint);
+
+#ifndef GL_VERSION_2_0
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#endif
+
+#ifdef _MSC_VER
+#define strcasecmp(x, y) _stricmp(x, y)
+#endif
+
+#include
+#include
+#include
+
+#include "getopt.h"
+
+static void usage(void)
+{
+ printf("version [-h] [-m MAJOR] [-n MINOR] [-d] [-l] [-f] [-p PROFILE]\n");
+ printf("available profiles: core compat\n");
+}
+
+static const char* get_profile_name(GLint mask)
+{
+ if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
+ return "compatibility";
+ if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
+ return "core";
+
+ return "unknown";
+}
+
+static void list_extensions(int major, int minor)
+{
+ int i;
+ GLint count;
+ const GLubyte* extensions;
+
+ printf("OpenGL context supported extensions:\n");
+
+ if (major > 2)
+ {
+ PFNGLGETSTRINGI glGetStringi = (PFNGLGETSTRINGI) glfwGetProcAddress("glGetStringi");
+ if (!glGetStringi)
+ {
+ fprintf(stderr, "Failed to retrieve glGetStringi entry point");
+ exit(EXIT_FAILURE);
+ }
+
+ glGetIntegerv(GL_NUM_EXTENSIONS, &count);
+
+ for (i = 0; i < count; i++)
+ puts((const char*) glGetStringi(GL_EXTENSIONS, i));
+ }
+ else
+ {
+ extensions = glGetString(GL_EXTENSIONS);
+ while (*extensions != '\0')
+ {
+ if (*extensions == ' ')
+ putchar('\n');
+ else
+ putchar(*extensions);
+
+ extensions++;
+ }
+ }
+
+ putchar('\n');
+}
+
+int main(int argc, char** argv)
+{
+ int ch, profile = 0, major = 1, minor = 1, revision;
+ GLboolean debug = GL_FALSE, forward = GL_FALSE, list = GL_FALSE;
+ GLint flags, mask;
+
+ while ((ch = getopt(argc, argv, "dfhlm:n:p:")) != -1)
+ {
+ switch (ch)
+ {
+ case 'd':
+ debug = GL_TRUE;
+ break;
+ case 'f':
+ forward = GL_TRUE;
+ break;
+ case 'h':
+ usage();
+ exit(0);
+ case 'l':
+ list = GL_TRUE;
+ break;
+ case 'm':
+ major = atoi(optarg);
+ break;
+ case 'n':
+ minor = atoi(optarg);
+ break;
+ case 'p':
+ if (strcasecmp(optarg, "core") == 0)
+ profile = GLFW_OPENGL_CORE_PROFILE;
+ else if (strcasecmp(optarg, "compat") == 0)
+ profile = GLFW_OPENGL_COMPAT_PROFILE;
+ else
+ {
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ break;
+ default:
+ usage();
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (!glfwInit())
+ {
+ fprintf(stderr, "Failed to initialize GLFW\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (major != 1 || minor != 1)
+ {
+ glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, major);
+ glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, minor);
+ }
+
+ if (debug)
+ glfwOpenWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
+
+ if (forward)
+ glfwOpenWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
+
+ if (profile != 0)
+ glfwOpenWindowHint(GLFW_OPENGL_PROFILE, profile);
+
+ // We assume here that we stand a better chance of success by leaving all
+ // possible details of pixel format selection to GLFW
+
+ if (!glfwOpenWindow(0, 0, 0, 0, 0, 0, 0, 0, GLFW_WINDOW))
+ {
+ glfwTerminate();
+
+ fprintf(stderr, "Failed to open GLFW window\n");
+ exit(EXIT_FAILURE);
+ }
+
+ // Report GLFW version
+
+ glfwGetVersion(&major, &minor, &revision);
+
+ printf("GLFW header version: %u.%u.%u\n",
+ GLFW_VERSION_MAJOR,
+ GLFW_VERSION_MINOR,
+ GLFW_VERSION_REVISION);
+
+ printf("GLFW library version: %u.%u.%u\n", major, minor, revision);
+
+ if (major != GLFW_VERSION_MAJOR ||
+ minor != GLFW_VERSION_MINOR ||
+ revision != GLFW_VERSION_REVISION)
+ printf("*** WARNING: GLFW version mismatch! ***\n");
+
+ // Report OpenGL version
+
+ printf("OpenGL context version string: \"%s\"\n", glGetString(GL_VERSION));
+
+ glfwGetGLVersion(&major, &minor, &revision);
+
+ printf("OpenGL context version parsed by GLFW: %u.%u.%u\n", major, minor, revision);
+
+ // Report OpenGL context properties
+
+ if (major >= 3)
+ {
+ glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
+ printf("OpenGL context flags:");
+
+ if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
+ puts(" forward-compatible");
+ else
+ puts(" none");
+ }
+
+ if (major > 3 || (major == 3 && minor >= 2))
+ {
+ glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
+ printf("OpenGL profile mask: 0x%08x (%s)\n", mask, get_profile_name(mask));
+ }
+
+ printf("OpenGL context renderer string: \"%s\"\n", glGetString(GL_RENDERER));
+ printf("OpenGL context vendor string: \"%s\"\n", glGetString(GL_VENDOR));
+
+ if (major > 1)
+ {
+ printf("OpenGL context shading language version: \"%s\"\n",
+ glGetString(GL_SHADING_LANGUAGE_VERSION));
+ }
+
+ // Report OpenGL extensions
+ if (list)
+ list_extensions(major, minor);
+
+ glfwTerminate();
+ exit(EXIT_SUCCESS);
+}
+