From f308228a19fe26fa83d56cbb62500818bfccea6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 11 Oct 2017 02:08:09 +0200 Subject: [PATCH 01/12] Documentation work Remove sentence describing GLFW-specific behavior. This describes the behavior of glfwUpdateGamepadMappings, whose behavior is a mix between the two related SDL functions, but is not part of the format. --- docs/input.dox | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/input.dox b/docs/input.dox index 6d444656..0eaa8ef8 100644 --- a/docs/input.dox +++ b/docs/input.dox @@ -786,7 +786,6 @@ functions. There is also the special `platform` field that specifies which platform the mapping is valid for. Possible values are `Windows`, `Mac OS X` and `Linux`. -Mappings without this field will always be considered valid. Below is an example of what a gamepad mapping might look like. It is the one built into GLFW for Xbox controllers accessed via the XInput API on Windows. From 66c0394ae19c24483a5228eeaa179945206768ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 18 Oct 2017 16:48:21 +0200 Subject: [PATCH 02/12] Fix typo in window guide Fixes #1099. --- docs/window.dox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/window.dox b/docs/window.dox index 5dbf15bf..39420804 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -87,7 +87,7 @@ By default, the original video mode of the monitor will be restored and the window iconified if it loses input focus, to allow the user to switch back to the desktop. This behavior can be disabled with the [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_hint) window hint, for example if you -wish to simultaneously cover multiple windows with full screen windows. +wish to simultaneously cover multiple monitors with full screen windows. If a monitor is disconnected, any window that is full screen on that monitor will be forced into windowed mode. See @ref monitor_event for more information. From 81963967e576e703df486df16c287aef21b40b1d Mon Sep 17 00:00:00 2001 From: siavashserver Date: Sat, 21 Oct 2017 18:55:03 +0330 Subject: [PATCH 03/12] Fix Doxygen navigation bar The Doxygen CSS changed significantly in a recent release. Closes #1100. --- docs/extra.css | 2 +- docs/extra.less | 40 +++++++++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/docs/extra.css b/docs/extra.css index df978c0c..42091cd1 100644 --- a/docs/extra.css +++ b/docs/extra.css @@ -1 +1 @@ -.sm-dox,.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted,.sm-dox ul a:hover{background:none;text-shadow:none}.sm-dox ul a:hover{background:#666;text-shadow:none}#main-nav,#navrow1,#navrow2,#navrow3,#navrow4,.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code{background:none}#titlearea,.footer,.contents,div.header,.memdoc,table.doxtable td,table.doxtable th,hr,.memSeparator{border:none}.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a,.reflist dt a.el,.levels span,.directory .levels span{text-shadow:none}.memdoc,dl.reflist dd{box-shadow:none}div.headertitle,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,table.doxtable code{padding:0}#nav-path,.directory .levels,span.lineno{display:none}html,#titlearea,.footer,tr.even,.directory tr.even,.doxtable tr:nth-child(even),.mdescLeft,.mdescRight,.memItemLeft,.memItemRight,code{background:#f2f2f2}body{color:#4d4d4d}h1,h2,h2.groupheader,h3,div.toc h3,h4,h5,h6,strong,em{color:#1a1a1a;border-bottom:none}h1{padding-top:0.5em;font-size:180%}h2{padding-top:0.5em;margin-bottom:0;font-size:140%}h3{padding-top:0.5em;margin-bottom:0;font-size:110%}.glfwheader{font-size:16px;height:64px;max-width:920px;min-width:800px;padding:0 32px;margin:0 auto}#glfwhome{line-height:64px;padding-right:48px;color:#666;font-size:2.5em;background:url("http://www.glfw.org/css/arrow.png") no-repeat right}.glfwnavbar{list-style-type:none;margin:0 auto;float:right}#glfwhome,.glfwnavbar li{float:left}.glfwnavbar a,.glfwnavbar a:visited{line-height:64px;margin-left:2em;display:block;color:#666}#glfwhome,.glfwnavbar a,.glfwnavbar a:visited{transition:.35s ease}#titlearea,.footer{color:#666}address.footer{text-align:center;padding:2em;margin-top:3em}#top{background:#666}#main-nav{max-width:960px;min-width:800px;margin:0 auto;font-size:13px}#navrow1,#navrow2,#navrow3,#navrow4{max-width:920px;min-width:800px;margin:0 auto;font-size:13px}.memtitle{display:none}.memproto,.memname{font-weight:bold;text-shadow:none}.tablist{height:36px;display:block;position:relative}.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a{color:#f2f2f2}.tablist li.current a{background:linear-gradient(to bottom, #ffa733 0, #f60 100%);box-shadow:inset 0 0 32px #f60;text-shadow:0 -1px 1px #b34700;color:#fff}.contents{min-height:590px}div.contents,div.header{max-width:920px;margin:0 auto;padding:0 32px;background:#fff none}table.doxtable th,dl.reflist dt{background:linear-gradient(to bottom, #ffa733 0, #f60 100%);box-shadow:inset 0 0 32px #f60;text-shadow:0 -1px 1px #b34700;text-align:left;color:#fff}dl.reflist dt a.el{color:#f60;padding:.2em;border-radius:4px;background-color:#ffe0cc}div.toc{float:none;width:auto}div.toc h3{font-size:1.17em}div.toc ul{padding-left:1.5em}div.toc li{font-size:1em;padding-left:0;list-style-type:disc}div.toc,.memproto,div.qindex,div.ah{background:linear-gradient(to bottom, #f2f2f2 0, #e6e6e6 100%);box-shadow:inset 0 0 32px #e6e6e6;text-shadow:0 1px 1px #fff;color:#1a1a1a;border:2px solid #e6e6e6;border-radius:4px}.paramname{color:#803300}dl.reflist dt{border:2px solid #f60;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom:none}dl.reflist dd{border:2px solid #f60;border-bottom-right-radius:4px;border-bottom-left-radius:4px;border-top:none}table.doxtable{border-collapse:inherit;border-spacing:0;border:2px solid #f60;border-radius:4px}a,a:hover,a:visited,a:visited:hover,.contents a:visited,.el,a.el:visited,#glfwhome:hover,.tablist a:hover,span.lineno a:hover{color:#f60;text-decoration:none}div.directory{border-collapse:inherit;border-spacing:0;border:2px solid #f60;border-radius:4px}hr,.memSeparator{height:2px;background:linear-gradient(to right, #f2f2f2 0, #d9d9d9 50%, #f2f2f2 100%)}dl.note,dl.pre,dl.post,dl.invariant{background:linear-gradient(to bottom, #ddfad1 0, #cbf7ba 100%);box-shadow:inset 0 0 32px #baf5a3;color:#1e5309;border:2px solid #afe599}dl.warning,dl.attention{background:linear-gradient(to bottom, #fae8d1 0, #f7ddba 100%);box-shadow:inset 0 0 32px #f5d1a3;color:#533309;border:2px solid #e5c499}dl.deprecated,dl.bug{background:linear-gradient(to bottom, #fad1e3 0, #f7bad6 100%);box-shadow:inset 0 0 32px #f5a3c8;color:#53092a;border:2px solid #e599bb}dl.todo,dl.test{background:linear-gradient(to bottom, #d1ecfa 0, #bae3f7 100%);box-shadow:inset 0 0 32px #a3daf5;color:#093a53;border:2px solid #99cce5}dl.note,dl.pre,dl.post,dl.invariant,dl.warning,dl.attention,dl.deprecated,dl.bug,dl.todo,dl.test{border-radius:4px;padding:1em;text-shadow:0 1px 1px #fff;margin:1em 0}.note a,.pre a,.post a,.invariant a,.warning a,.attention a,.deprecated a,.bug a,.todo a,.test a,.note a:visited,.pre a:visited,.post a:visited,.invariant a:visited,.warning a:visited,.attention a:visited,.deprecated a:visited,.bug a:visited,.todo a:visited,.test a:visited{color:inherit}div.line{line-height:inherit}div.fragment,pre.fragment{background:#f2f2f2;border-radius:4px;border:none;padding:1em;overflow:auto;border-left:4px solid #ccc;margin:1em 0}.lineno a,.lineno a:visited,.line,pre.fragment{color:#4d4d4d}span.preprocessor,span.comment{color:#007899}a.code,a.code:visited{color:#e64500}span.keyword,span.keywordtype,span.keywordflow{color:#404040;font-weight:bold}span.stringliteral{color:#360099}code{padding:.1em;border-radius:4px} +.sm-dox,.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted,.sm-dox ul a:hover{background:none;text-shadow:none}.sm-dox a span.sub-arrow{border-color:#f2f2f2 transparent transparent transparent}.sm-dox a span.sub-arrow:active,.sm-dox a span.sub-arrow:focus,.sm-dox a span.sub-arrow:hover,.sm-dox a:hover span.sub-arrow{border-color:#f60 transparent transparent transparent}.sm-dox ul a span.sub-arrow:active,.sm-dox ul a span.sub-arrow:focus,.sm-dox ul a span.sub-arrow:hover,.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent #f60}.sm-dox ul a:hover{background:#666;text-shadow:none}.sm-dox ul.sm-nowrap a{color:#4d4d4d;text-shadow:none}#main-nav,#main-menu,#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code{background:none}#titlearea,.footer,.contents,div.header,.memdoc,table.doxtable td,table.doxtable th,hr,.memSeparator{border:none}#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.reflist dt a.el,.levels span,.directory .levels span{text-shadow:none}.memdoc,dl.reflist dd{box-shadow:none}div.headertitle,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,table.doxtable code{padding:0}#nav-path,.directory .levels,span.lineno{display:none}html,#titlearea,.footer,tr.even,.directory tr.even,.doxtable tr:nth-child(even),.mdescLeft,.mdescRight,.memItemLeft,.memItemRight,code{background:#f2f2f2}body{color:#4d4d4d}h1,h2,h2.groupheader,h3,div.toc h3,h4,h5,h6,strong,em{color:#1a1a1a;border-bottom:none}h1{padding-top:.5em;font-size:180%}h2{padding-top:.5em;margin-bottom:0;font-size:140%}h3{padding-top:.5em;margin-bottom:0;font-size:110%}.glfwheader{font-size:16px;height:64px;max-width:920px;min-width:800px;padding:0 32px;margin:0 auto}#glfwhome{line-height:64px;padding-right:48px;color:#666;font-size:2.5em;background:url("http://www.glfw.org/css/arrow.png") no-repeat right}.glfwnavbar{list-style-type:none;margin:0 auto;float:right}#glfwhome,.glfwnavbar li{float:left}.glfwnavbar a,.glfwnavbar a:visited{line-height:64px;margin-left:2em;display:block;color:#666}#glfwhome,.glfwnavbar a,.glfwnavbar a:visited{transition:.35s ease}#titlearea,.footer{color:#666}address.footer{text-align:center;padding:2em;margin-top:3em}#top{background:#666}#main-nav{max-width:960px;min-width:800px;margin:0 auto;font-size:13px}#main-menu{max-width:920px;min-width:800px;margin:0 auto;font-size:13px}.memtitle{display:none}.memproto,.memname{font-weight:bold;text-shadow:none}#main-menu{height:36px;display:block;position:relative}#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li{color:#f2f2f2}#main-menu li ul.sm-nowrap li a{color:#4d4d4d}#main-menu li ul.sm-nowrap li a:hover{color:#f60}.contents{min-height:590px}div.contents,div.header{max-width:920px;margin:0 auto;padding:0 32px;background:#fff none}table.doxtable th,dl.reflist dt{background:linear-gradient(to bottom, #ffa733 0, #f60 100%);box-shadow:inset 0 0 32px #f60;text-shadow:0 -1px 1px #b34700;text-align:left;color:#fff}dl.reflist dt a.el{color:#f60;padding:.2em;border-radius:4px;background-color:#ffe0cc}div.toc{float:none;width:auto}div.toc h3{font-size:1.17em}div.toc ul{padding-left:1.5em}div.toc li{font-size:1em;padding-left:0;list-style-type:disc}div.toc,.memproto,div.qindex,div.ah{background:linear-gradient(to bottom, #f2f2f2 0, #e6e6e6 100%);box-shadow:inset 0 0 32px #e6e6e6;text-shadow:0 1px 1px #fff;color:#1a1a1a;border:2px solid #e6e6e6;border-radius:4px}.paramname{color:#803300}dl.reflist dt{border:2px solid #f60;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom:none}dl.reflist dd{border:2px solid #f60;border-bottom-right-radius:4px;border-bottom-left-radius:4px;border-top:none}table.doxtable{border-collapse:inherit;border-spacing:0;border:2px solid #f60;border-radius:4px}a,a:hover,a:visited,a:visited:hover,.contents a:visited,.el,a.el:visited,#glfwhome:hover,#main-menu a:hover,span.lineno a:hover{color:#f60;text-decoration:none}div.directory{border-collapse:inherit;border-spacing:0;border:2px solid #f60;border-radius:4px}hr,.memSeparator{height:2px;background:linear-gradient(to right, #f2f2f2 0, #d9d9d9 50%, #f2f2f2 100%)}dl.note,dl.pre,dl.post,dl.invariant{background:linear-gradient(to bottom, #ddfad1 0, #cbf7ba 100%);box-shadow:inset 0 0 32px #baf5a3;color:#1e5309;border:2px solid #afe599}dl.warning,dl.attention{background:linear-gradient(to bottom, #fae8d1 0, #f7ddba 100%);box-shadow:inset 0 0 32px #f5d1a3;color:#533309;border:2px solid #e5c499}dl.deprecated,dl.bug{background:linear-gradient(to bottom, #fad1e3 0, #f7bad6 100%);box-shadow:inset 0 0 32px #f5a3c8;color:#53092a;border:2px solid #e599bb}dl.todo,dl.test{background:linear-gradient(to bottom, #d1ecfa 0, #bae3f7 100%);box-shadow:inset 0 0 32px #a3daf5;color:#093a53;border:2px solid #99cce5}dl.note,dl.pre,dl.post,dl.invariant,dl.warning,dl.attention,dl.deprecated,dl.bug,dl.todo,dl.test{border-radius:4px;padding:1em;text-shadow:0 1px 1px #fff;margin:1em 0}.note a,.pre a,.post a,.invariant a,.warning a,.attention a,.deprecated a,.bug a,.todo a,.test a,.note a:visited,.pre a:visited,.post a:visited,.invariant a:visited,.warning a:visited,.attention a:visited,.deprecated a:visited,.bug a:visited,.todo a:visited,.test a:visited{color:inherit}div.line{line-height:inherit}div.fragment,pre.fragment{background:#f2f2f2;border-radius:4px;border:none;padding:1em;overflow:auto;border-left:4px solid #ccc;margin:1em 0}.lineno a,.lineno a:visited,.line,pre.fragment{color:#4d4d4d}span.preprocessor,span.comment{color:#007899}a.code,a.code:visited{color:#e64500}span.keyword,span.keywordtype,span.keywordflow{color:#404040;font-weight:bold}span.stringliteral{color:#360099}code{padding:.1em;border-radius:4px} diff --git a/docs/extra.less b/docs/extra.less index 9221459a..53e94f75 100644 --- a/docs/extra.less +++ b/docs/extra.less @@ -81,12 +81,29 @@ text-shadow:none; } +.sm-dox a span.sub-arrow { + border-color:@navbar-link-color transparent transparent transparent; +} + +.sm-dox a span.sub-arrow:active,.sm-dox a span.sub-arrow:focus,.sm-dox a span.sub-arrow:hover,.sm-dox a:hover span.sub-arrow { + border-color:@default-link-color transparent transparent transparent; +} + +.sm-dox ul a span.sub-arrow:active,.sm-dox ul a span.sub-arrow:focus,.sm-dox ul a span.sub-arrow:hover,.sm-dox ul a:hover span.sub-arrow { + border-color:transparent transparent transparent @default-link-color; +} + .sm-dox ul a:hover { background:@header-footer-link-color; text-shadow:none; } -#main-nav,#navrow1,#navrow2,#navrow3,#navrow4,.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code { +.sm-dox ul.sm-nowrap a { + color:@default-text-color; + text-shadow:none; +} + +#main-nav,#main-menu,#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.memdoc,dl.reflist dd,div.toc li,.ah,span.lineno,span.lineno a,span.lineno a:hover,.note code,.pre code,.post code,.invariant code,.warning code,.attention code,.deprecated code,.bug code,.todo code,.test code,.doxtable code { background:none; } @@ -94,7 +111,7 @@ border:none; } -.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a,.reflist dt a.el,.levels span,.directory .levels span { +#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li,.reflist dt a.el,.levels span,.directory .levels span { text-shadow:none; } @@ -199,7 +216,7 @@ address.footer { font-size:13px; } -#navrow1,#navrow2,#navrow3,#navrow4 { +#main-menu { max-width:920px; min-width:800px; margin:0 auto; @@ -215,21 +232,22 @@ address.footer { text-shadow:none; } -.tablist { +#main-menu { height:36px; display:block; position:relative; } -.tablist a,.tablist a:visited,.tablist a:hover,.tablist li,.tablist li.current a { +#main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li { color:@navbar-link-color; } -.tablist li.current a { - background:linear-gradient(to bottom,@tab-background-color2 0%,@tab-background-color1 100%); - box-shadow:inset 0 0 32px @tab-background-color1; - text-shadow:0 -1px 1px darken(@tab-background-color1, 15%); - color:@tab-text-color; +#main-menu li ul.sm-nowrap li a { + color:@default-text-color; +} + +#main-menu li ul.sm-nowrap li a:hover { + color:@default-link-color; } .contents { @@ -311,7 +329,7 @@ table.doxtable { border-radius:4px; } -a,a:hover,a:visited,a:visited:hover,.contents a:visited,.el,a.el:visited,#glfwhome:hover,.tablist a:hover,span.lineno a:hover { +a,a:hover,a:visited,a:visited:hover,.contents a:visited,.el,a.el:visited,#glfwhome:hover,#main-menu a:hover,span.lineno a:hover { color:@default-link-color; text-decoration:none; } From 1be81a15409ab5a485ce71cade96ff22e7e698fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 22 Oct 2017 16:27:17 +0200 Subject: [PATCH 04/12] Documentation work --- docs/build.dox | 14 +++++++------- docs/compile.dox | 8 ++++---- docs/context.dox | 2 +- docs/input.dox | 12 ++++++------ docs/intro.dox | 10 +++++----- docs/moving.dox | 2 +- docs/quick.dox | 12 +++++------- docs/window.dox | 10 +++++----- include/GLFW/glfw3.h | 14 ++++++-------- 9 files changed, 40 insertions(+), 44 deletions(-) diff --git a/docs/build.dox b/docs/build.dox index e428594e..18ce13ce 100644 --- a/docs/build.dox +++ b/docs/build.dox @@ -183,8 +183,8 @@ This section is about using CMake to compile and link GLFW along with your application. If you want to use an installed binary instead, see @ref build_link_cmake_package. -With just a few changes to your `CMakeLists.txt` you can have the GLFW source -tree built along with your application. +With a few changes to your `CMakeLists.txt` you can have the GLFW source tree +built along with your application. When including GLFW as part of your build, you probably don't want to build the GLFW tests, examples and documentation. To disable these, set the corresponding @@ -249,7 +249,7 @@ This section is about using CMake to link GLFW after it has been built and installed. If you want to build it along with your application instead, see @ref build_link_cmake_source. -With just a few changes to your `CMakeLists.txt`, you can locate the package and +With a few changes to your `CMakeLists.txt` you can locate the package and target files generated when GLFW is installed. @code{.cmake} @@ -312,8 +312,8 @@ GLFW library may look like this: cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --static --libs glfw3` @endcode -If you are using the shared version of the GLFW library, simply omit the -`--static` flag. +If you are using the shared version of the GLFW library, omit the `--static` +flag. @code{.sh} cc `pkg-config --cflags glfw3` -o myprog myprog.c `pkg-config --libs glfw3` @@ -350,8 +350,8 @@ cc `pkg-config --cflags glfw3 glu` -o myprog myprog.c `pkg-config --static --lib @subsection build_link_xcode With Xcode on macOS -If you are using the dynamic library version of GLFW, simply add it to the -project dependencies. +If you are using the dynamic library version of GLFW, add it to the project +dependencies. If you are using the static library version of GLFW, add it and the Cocoa, OpenGL, IOKit and CoreVideo frameworks to the project as dependencies. They can diff --git a/docs/compile.dox b/docs/compile.dox index 35d65732..4486156e 100644 --- a/docs/compile.dox +++ b/docs/compile.dox @@ -13,7 +13,7 @@ build applications that use GLFW, see @ref build_guide. GLFW uses [CMake](http://www.cmake.org/) to generate project files or makefiles for a particular development environment. If you are on a Unix-like system such as Linux or FreeBSD or have a package system like Fink, MacPorts, Cygwin or -Homebrew, you can simply install its CMake package. If not, you can download +Homebrew, you can install its CMake package. If not, you can download installers for Windows and macOS from the [CMake website](http://www.cmake.org/). @@ -33,9 +33,9 @@ below. @subsubsection compile_deps_msvc Dependencies for Visual C++ on Windows -The Microsoft Platform SDK that is installed along with Visual C++ already -contains all the necessary headers, link libraries and tools except for CMake. -Move on to @ref compile_generate. +The Windows SDK bundled with Visual C++ already contains all the necessary +headers, link libraries and tools except for CMake. Move on to @ref +compile_generate. @subsubsection compile_deps_mingw Dependencies for MinGW or MinGW-w64 on Windows diff --git a/docs/context.dox b/docs/context.dox index 9aa72a5c..61292849 100644 --- a/docs/context.dox +++ b/docs/context.dox @@ -61,7 +61,7 @@ information. The name and number of this chapter unfortunately varies between versions and APIs, but has at times been named _Shared Objects and Multiple Contexts_. -GLFW comes with a simple object sharing test program called `sharing`. +GLFW comes with a barebones object sharing test program called `sharing`. @subsection context_offscreen Offscreen contexts diff --git a/docs/input.dox b/docs/input.dox index 0eaa8ef8..318d48d5 100644 --- a/docs/input.dox +++ b/docs/input.dox @@ -203,9 +203,9 @@ void character_callback(GLFWwindow* window, unsigned int codepoint) } @endcode -If you wish to receive even those Unicode code points generated with modifier -key combinations that a plain text field would ignore, or just want to know -exactly what modifier keys were used, set a character with modifiers callback. +If you also wish to receive those Unicode code points generated with modifier +key combinations that a plain text field would ignore, or want to know exactly +what modifier keys were used, set a character with modifiers callback. @code glfwSetCharModsCallback(window, charmods_callback); @@ -297,8 +297,8 @@ is provided normally via both the cursor position callback and through polling. other features of GLFW. It is not supported and will not work as robustly as `GLFW_CURSOR_DISABLED`. -If you just wish the cursor to become hidden when it is over a window, set -the cursor mode to `GLFW_CURSOR_HIDDEN`. +If you only wish the cursor to become hidden when it is over a window but still +want it to behave normally, set the cursor mode to `GLFW_CURSOR_HIDDEN`. @code glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); @@ -501,7 +501,7 @@ void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) } @endcode -A simple mouse wheel, being vertical, provides offsets along the Y-axis. +A normal mouse wheel, being vertical, provides offsets along the Y-axis. @section joystick Joystick input diff --git a/docs/intro.dox b/docs/intro.dox index 65aeef68..46a445aa 100644 --- a/docs/intro.dox +++ b/docs/intro.dox @@ -55,13 +55,13 @@ if (!glfwInit()) If any part of initialization fails, any parts that succeeded are terminated as if @ref glfwTerminate had been called. The library only needs to be initialized -once and additional calls to an already initialized library will simply return +once and additional calls to an already initialized library will return `GLFW_TRUE` immediately. Once the library has been successfully initialized, it should be terminated before the application exits. Modern systems are very good at freeing resources -allocated by programs that simply exit, but GLFW sometimes has to change global -system settings and these might not be restored without termination. +allocated by programs that exit, but GLFW sometimes has to change global system +settings and these might not be restored without termination. @subsection init_hints Initialization hints @@ -79,8 +79,8 @@ during initialization. Once GLFW has been initialized, any values you set will be ignored until the library is terminated and initialized again. Some hints are platform specific. These may be set on any platform but they -will only affect their specific platform. Other platforms will simply ignore -them. Setting these hints requires no platform specific headers or functions. +will only affect their specific platform. Other platforms will ignore them. +Setting these hints requires no platform specific headers or functions. @subsubsection init_hints_shared Shared init hints diff --git a/docs/moving.dox b/docs/moving.dox index af3da61c..0f33a7e5 100644 --- a/docs/moving.dox +++ b/docs/moving.dox @@ -221,7 +221,7 @@ GLFW 2, windows and contexts created with GLFW 3 will never be destroyed unless you choose them to be. Each window now has a close flag that is set to `GLFW_TRUE` when the user attempts to close that window. By default, nothing else happens and the window stays visible. It is then up to you to either destroy -the window, take some other action or simply ignore the request. +the window, take some other action or ignore the request. You can query the close flag at any time with @ref glfwWindowShouldClose and set it at any time with @ref glfwSetWindowShouldClose. diff --git a/docs/quick.dox b/docs/quick.dox index dc1a2f8d..ff2c6f06 100644 --- a/docs/quick.dox +++ b/docs/quick.dox @@ -69,7 +69,7 @@ if (!glfwInit()) } @endcode -Note that `GLFW_TRUE` and `GLFW_FALSE` are and will always be just one and zero. +Note that `GLFW_TRUE` and `GLFW_FALSE` are and will always be one and zero. When you are done using GLFW, typically just before the application exits, you need to terminate GLFW. @@ -86,14 +86,12 @@ functions that require it. @subsection quick_capture_error Setting an error callback Most events are reported through callbacks, whether it's a key being pressed, -a GLFW window being moved, or an error occurring. Callbacks are simply -C functions (or C++ static methods) that are called by GLFW with arguments -describing the event. +a GLFW window being moved, or an error occurring. Callbacks are C functions (or +C++ static methods) that are called by GLFW with arguments describing the event. In case a GLFW function fails, an error is reported to the GLFW error callback. You can receive these reports with an error callback. This function must have -the signature below. This simple error callback just prints the error -description to `stderr`. +the signature below but may do anything permitted in other callbacks. @code void error_callback(int error, const char* description) @@ -249,7 +247,7 @@ You can also set a framebuffer size callback using @ref glfwSetFramebufferSizeCallback and be notified when the size changes. Actual rendering with OpenGL is outside the scope of this tutorial, but there -are [many](https://open.gl/) [excellent](http://learnopengl.com/) +are [many](https://open.gl/) [excellent](https://learnopengl.com/) [tutorial](http://openglbook.com/) [sites](http://ogldev.atspace.co.uk/) that teach modern OpenGL. Some of them use GLFW to create the context and window while others use GLUT or SDL, but remember that OpenGL itself always works the diff --git a/docs/window.dox b/docs/window.dox index 39420804..85663e77 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -77,7 +77,7 @@ GLFWvidmode.blueBits | @ref GLFW_BLUE_BITS hint GLFWvidmode.refreshRate | @ref GLFW_REFRESH_RATE hint Once you have a full screen window, you can change its resolution, refresh rate -and monitor with @ref glfwSetWindowMonitor. If you just need change its +and monitor with @ref glfwSetWindowMonitor. If you only need change its resolution you can also call @ref glfwSetWindowSize. In all cases, the new video mode will be selected the same way as the video mode chosen by @ref glfwCreateWindow. If the window has an OpenGL or OpenGL ES context, it will be @@ -99,7 +99,7 @@ If the closest match for the desired video mode is the current one, the video mode will not be changed, making window creation faster and application switching much smoother. This is sometimes called _windowed full screen_ or _borderless full screen_ window and counts as a full screen window. To create -such a window, simply request the current video mode. +such a window, request the current video mode. @code const GLFWvidmode* mode = glfwGetVideoMode(monitor); @@ -151,8 +151,8 @@ and reset all at once to their defaults with @ref glfwDefaultWindowHints. Some hints are platform specific. These are always valid to set on any platform but they will only affect their specific platform. Other platforms -will simply ignore them. Setting these hints requires no platform specific -headers or calls. +will ignore them. Setting these hints requires no platform specific headers or +calls. Note that hints need to be set _before_ the creation of the window and context you wish to have the specified attributes. @@ -694,7 +694,7 @@ glfwSetWindowAspectRatio(window, 16, 9); The aspect ratio is specified as a numerator and denominator, corresponding to the width and height, respectively. If you want a window to maintain its -current aspect ratio, simply use its current size as the ratio. +current aspect ratio, use its current size as the ratio. @code int width, height; diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 819d2cd6..8e6bc42c 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -274,14 +274,14 @@ extern "C" { /*! @brief One. * * One. Seriously. You don't _need_ to use this symbol in your code. It's - * just semantic sugar for the number 1. You can use `1` or `true` or `_True` + * semantic sugar for the number 1. You can also use `1` or `true` or `_True` * or `GL_TRUE` or whatever you want. */ #define GLFW_TRUE 1 /*! @brief Zero. * * Zero. Seriously. You don't _need_ to use this symbol in your code. It's - * just just semantic sugar for the number 0. You can use `0` or `false` or + * semantic sugar for the number 0. You can also use `0` or `false` or * `_False` or `GL_FALSE` or whatever you want. */ #define GLFW_FALSE 0 @@ -1629,9 +1629,8 @@ GLFWAPI void glfwTerminate(void); * again. * * Some hints are platform specific. These may be set on any platform but they - * will only affect their specific platform. Other platforms will simply - * ignore them. Setting these hints requires no platform specific headers or - * functions. + * will only affect their specific platform. Other platforms will ignore them. + * Setting these hints requires no platform specific headers or functions. * * @param[in] hint The [init hint](@ref init_hints) to set. * @param[in] value The new value of the init hint. @@ -1664,9 +1663,8 @@ GLFWAPI void glfwInitHint(int hint, int value); * again. * * Some hints are platform specific. These may be set on any platform but they - * will only affect their specific platform. Other platforms will simply - * ignore them. Setting these hints requires no platform specific headers or - * functions. + * will only affect their specific platform. Other platforms will ignore them. + * Setting these hints requires no platform specific headers or functions. * * @param[in] hint The [init hint](@ref init_hints) to set. * @param[in] value The new value of the init hint. From 16bf872117896fb88493403157fcd367303fd1f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 29 Aug 2017 19:19:00 +0200 Subject: [PATCH 05/12] Add content scale queries This adds glfwGetWindowContentScale and glfwGetMonitorContentScale for querying the recommended drawing scale factor for DPI-aware rendering. Parts of this patch are based on code by @ferreiradaselva. Fixes #235. Fixes #439. Fixes #677. Fixes #845. Fixes #898. --- README.md | 2 ++ docs/monitor.dox | 27 ++++++++++++++++---- docs/news.dox | 9 +++++++ docs/window.dox | 20 +++++++++++++++ include/GLFW/glfw3.h | 60 ++++++++++++++++++++++++++++++++++++++++++++ src/cocoa_monitor.m | 45 +++++++++++++++++++++++++++++++++ src/cocoa_platform.h | 1 + src/cocoa_window.m | 12 +++++++++ src/internal.h | 2 ++ src/mir_monitor.c | 9 +++++++ src/mir_window.c | 9 +++++++ src/monitor.c | 15 +++++++++++ src/null_monitor.c | 9 +++++++ src/null_window.c | 9 +++++++ src/win32_init.c | 2 ++ src/win32_monitor.c | 50 ++++++++++++++++++++++++++++++------ src/win32_platform.h | 11 ++++++++ src/win32_window.c | 21 ++++++---------- src/window.c | 15 +++++++++++ src/wl_monitor.c | 9 +++++++ src/wl_window.c | 9 +++++++ src/x11_init.c | 40 +++++++++++++++++++++++++++++ src/x11_monitor.c | 9 +++++++ src/x11_platform.h | 2 ++ src/x11_window.c | 9 +++++++ tests/monitors.c | 9 ++++--- 26 files changed, 387 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 01b159c9..a890ac09 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,8 @@ information on what to include when reporting a bug. gamepad mapping (#900) - Added `glfwGetGamepadState` function, `GLFW_GAMEPAD_*` and `GLFWgamepadstate` for retrieving gamepad input state (#900) +- Added `glfwGetWindowContentScale` and `glfwGetMonitorContentScale` for + DPI-aware rendering (#235,#439,#677,#845,#898) - Added `glfwRequestWindowAttention` function for requesting attention from the user (#732,#988) - Added `glfwGetKeyScancode` function that allows retrieving platform dependent diff --git a/docs/monitor.dox b/docs/monitor.dox index 708461f5..7245f70c 100644 --- a/docs/monitor.dox +++ b/docs/monitor.dox @@ -131,17 +131,34 @@ current _resolution_, i.e. the width and height of its current [video mode](@ref monitor_modes). @code -int widthMM, heightMM; -glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM); +int width_mm, height_mm; +glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm); @endcode -This can, for example, be used together with the current video mode to calculate -the DPI of a monitor. +While this can be used to calculate the raw DPI of a monitor, this is often not +useful. Instead use the [monitor content scale](@ref monitor_scale) and +[window content scale](@ref window_scale) to scale your content. + + +@subsection monitor_scale Content scale + +The content scale for a monitor can be retrieved with @ref +glfwGetMonitorContentScale. @code -const double dpi = mode->width / (widthMM / 25.4); +float xscale, yscale; +glfwGetMonitorContentScale(monitor, &xscale, &yscale); @endcode +The content scale is the ratio between the current DPI and the platform's +default DPI. If you scale all pixel dimensions by this scale then your content +should appear at an appropriate size. This is especially important for text and +any UI elements. + +The content scale may depend on both the monitor resolution and pixel density +and on user settings. It may be very different from the raw DPI calculated from +the physical size and current resolution. + @subsection monitor_pos Virtual position diff --git a/docs/news.dox b/docs/news.dox index 86b68c41..03a9c8dc 100644 --- a/docs/news.dox +++ b/docs/news.dox @@ -58,6 +58,15 @@ windows with @ref glfwSetWindowAttrib. @see @ref window_attribs +@subsection news_33_contentscale Content scale queries for DPI-aware rendering + +GLFW now supports querying the window and monitor content scale, i.e. the ratio +between the current DPI and the platform's default DPI, with @ref +glfwGetWindowContentScale and @ref glfwGetMonitorContentScale. + +@see @ref window_scale + + @subsection news_33_inithint Support for initialization hints GLFW now supports setting library initialization hints with @ref glfwInitHint diff --git a/docs/window.dox b/docs/window.dox index 85663e77..7961e028 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -663,6 +663,26 @@ The size of a framebuffer may change independently of the size of a window, for example if the window is dragged between a regular monitor and a high-DPI one. +@subsection window_scale Window content scale + +The content scale for a window can be retrieved with @ref +glfwGetWindowContentScale. + +@code +float xscale, yscale; +glfwGetWindowContentScale(window, &xscale, &yscale); +@endcode + +The content scale of a window is the ratio between the current DPI and the +platform's default DPI. If you scale all pixel dimensions by this scale then +your content should appear at an appropriate size. This is especially important +for text and any UI elements. + +On systems where each monitors can have its own content scale, the window +content scale will depend on which monitor the system considers the window to be +on. + + @subsection window_sizelimits Window size limits The minimum and maximum size of the client area of a windowed mode window can be diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 8e6bc42c..0ba409b0 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1926,6 +1926,36 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos); */ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int* heightMM); +/*! @brief Retrieves the content scale for the specified monitor. + * + * This function retrieves the content scale for the specified monitor. The + * content scale is the ratio between the current DPI and the platform's + * default DPI. If you scale all pixel dimensions by this scale then your + * content should appear at an appropriate size. This is especially important + * for text and any UI elements. + * + * The content scale may depend on both the monitor resolution and pixel + * density and on user settings. It may be very different from the raw DPI + * calculated from the physical size and current resolution. + * + * @param[in] monitor The monitor to query. + * @param[out] xscale Where to store the x-axis content scale, or `NULL`. + * @param[out] yscale Where to store the y-axis content scale, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_scale + * @sa @ref glfwGetWindowContentScale + * + * @since Added in version 3.3. + * + * @ingroup monitor + */ +GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* monitor, float* xscale, float* yscale); + /*! @brief Returns the name of the specified monitor. * * This function returns a human-readable name, encoded as UTF-8, of the @@ -2774,6 +2804,36 @@ GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height) */ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int* right, int* bottom); +/*! @brief Retrieves the content scale for the specified window. + * + * This function retrieves the content scale for the specified window. The + * content scale is the ratio between the current DPI and the platform's + * default DPI. If you scale all pixel dimensions by this scale then your + * content should appear at an appropriate size. This is especially important + * for text and any UI elements. + * + * On systems where each monitors can have its own content scale, the window + * content scale will depend on which monitor the system considers the window + * to be on. + * + * @param[in] window The window to query. + * @param[out] xscale Where to store the x-axis content scale, or `NULL`. + * @param[out] yscale Where to store the y-axis content scale, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_scale + * @sa @ref glfwGetMonitorContentScale + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwGetWindowContentScale(GLFWwindow* window, float* xscale, float* yscale); + /*! @brief Iconifies the specified window. * * This function iconifies (minimizes) the specified window if it was diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 6020599f..6108342c 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -229,6 +229,9 @@ void _glfwPollMonitorsNS(void) displays = calloc(displayCount, sizeof(CGDirectDisplayID)); CGGetOnlineDisplayList(displayCount, displays, &displayCount); + for (i = 0; i < _glfw.monitorCount; i++) + _glfw.monitors[i]->ns.screen = nil; + disconnectedCount = _glfw.monitorCount; if (disconnectedCount) { @@ -371,6 +374,48 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) *ypos = (int) bounds.origin.y; } +void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, + float* xscale, float* yscale) +{ + if (!monitor->ns.screen) + { + NSUInteger i; + NSArray* screens = [NSScreen screens]; + + for (i = 0; i < [screens count]; i++) + { + NSScreen* screen = [screens objectAtIndex:i]; + NSNumber* displayID = + [[screen deviceDescription] objectForKey:@"NSScreenNumber"]; + + // HACK: Compare unit numbers instead of display IDs to work around + // display replacement on machines with automatic graphics + // switching + if (monitor->ns.unitNumber == + CGDisplayUnitNumber([displayID unsignedIntValue])) + { + monitor->ns.screen = screen; + break; + } + } + + if (i == [screens count]) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Cocoa: Failed to find a screen for monitor"); + return; + } + } + + const NSRect points = [monitor->ns.screen frame]; + const NSRect pixels = [monitor->ns.screen convertRectToBacking:points]; + + if (xscale) + *xscale = (float) (pixels.size.width / points.size.width); + if (yscale) + *yscale = (float) (pixels.size.height / points.size.height); +} + GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) { CFArrayRef modes; diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index f0ba4e85..61d0ee91 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -135,6 +135,7 @@ typedef struct _GLFWmonitorNS CGDirectDisplayID displayID; CGDisplayModeRef previousMode; uint32_t unitNumber; + id screen; } _GLFWmonitorNS; diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 0a3bcd54..4c9dea90 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1288,6 +1288,18 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, *bottom = contentRect.origin.y - frameRect.origin.y; } +void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, + float* xscale, float* yscale) +{ + const NSRect points = [window->ns.view frame]; + const NSRect pixels = [window->ns.view convertRectToBacking:points]; + + if (xscale) + *xscale = (float) (pixels.size.width / points.size.width); + if (yscale) + *yscale = (float) (pixels.size.height / points.size.height); +} + void _glfwPlatformIconifyWindow(_GLFWwindow* window) { [window->ns.object miniaturize:nil]; diff --git a/src/internal.h b/src/internal.h index b9f55da7..39494340 100644 --- a/src/internal.h +++ b/src/internal.h @@ -641,6 +641,7 @@ const char* _glfwPlatformGetScancodeName(int scancode); int _glfwPlatformGetKeyScancode(int key); void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos); +void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, float* xscale, float* yscale); GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count); void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode); void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp); @@ -670,6 +671,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, int minwidth, int min void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom); void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height); void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, int* left, int* top, int* right, int* bottom); +void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, float* xscale, float* yscale); void _glfwPlatformIconifyWindow(_GLFWwindow* window); void _glfwPlatformRestoreWindow(_GLFWwindow* window); void _glfwPlatformMaximizeWindow(_GLFWwindow* window); diff --git a/src/mir_monitor.c b/src/mir_monitor.c index 26848506..b300cac0 100644 --- a/src/mir_monitor.c +++ b/src/mir_monitor.c @@ -88,6 +88,15 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) *ypos = monitor->mir.y; } +void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, + float* xscale, float* yscale) +{ + if (xscale) + *xscale = 1.f; + if (yscale) + *yscale = 1.f; +} + static void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf) { switch (pf) diff --git a/src/mir_window.c b/src/mir_window.c index 8b763de1..c752cdb4 100644 --- a/src/mir_window.c +++ b/src/mir_window.c @@ -515,6 +515,15 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height) *height = window->mir.height; } +void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, + float* xscale, float* yscale) +{ + if (xscale) + *xscale = 1.f; + if (yscale) + *yscale = 1.f; +} + void _glfwPlatformIconifyWindow(_GLFWwindow* window) { MirWindowSpec* spec; diff --git a/src/monitor.c b/src/monitor.c index 4acecd58..40b24132 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -314,6 +314,21 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* *heightMM = monitor->heightMM; } +GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle, + float* xscale, float* yscale) +{ + _GLFWmonitor* monitor = (_GLFWmonitor*) handle; + assert(monitor != NULL); + + if (xscale) + *xscale = 0.f; + if (yscale) + *yscale = 0.f; + + _GLFW_REQUIRE_INIT(); + _glfwPlatformGetMonitorContentScale(monitor, xscale, yscale); +} + GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle; diff --git a/src/null_monitor.c b/src/null_monitor.c index f5678bbc..007dd1aa 100644 --- a/src/null_monitor.c +++ b/src/null_monitor.c @@ -36,6 +36,15 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) { } +void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, + float* xscale, float* yscale) +{ + if (xscale) + *xscale = 1.f; + if (yscale) + *yscale = 1.f; +} + GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) { return NULL; diff --git a/src/null_window.c b/src/null_window.c index 33ff6c33..3cc3905d 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -139,6 +139,15 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, { } +void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, + float* xscale, float* yscale) +{ + if (xscale) + *xscale = 1.f; + if (yscale) + *yscale = 1.f; +} + void _glfwPlatformIconifyWindow(_GLFWwindow* window) { } diff --git a/src/win32_init.c b/src/win32_init.c index 0531ff13..ee7ccfda 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -151,6 +151,8 @@ static GLFWbool loadLibraries(void) { _glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness) GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness"); + _glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor) + GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor"); } return GLFW_TRUE; diff --git a/src/win32_monitor.c b/src/win32_monitor.c index 76fbc0d8..74dd8252 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -60,6 +60,7 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter, DISPLAY_DEVICEW* display) { _GLFWmonitor* monitor; + int widthMM, heightMM; char* name; HDC dc; DEVMODEW dm; @@ -72,13 +73,26 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter, if (!name) return NULL; + ZeroMemory(&dm, sizeof(dm)); + dm.dmSize = sizeof(dm); + EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm); + dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL); - monitor = _glfwAllocMonitor(name, - GetDeviceCaps(dc, HORZSIZE), - GetDeviceCaps(dc, VERTSIZE)); + if (IsWindows8Point1OrGreater()) + { + widthMM = GetDeviceCaps(dc, HORZSIZE); + heightMM = GetDeviceCaps(dc, VERTSIZE); + } + else + { + widthMM = (int) (dm.dmPelsWidth * 25.4f / GetDeviceCaps(dc, LOGPIXELSX)); + heightMM = (int) (dm.dmPelsHeight * 25.4f / GetDeviceCaps(dc, LOGPIXELSY)); + } DeleteDC(dc); + + monitor = _glfwAllocMonitor(name, widthMM, heightMM); free(name); if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED) @@ -101,10 +115,6 @@ static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter, NULL, NULL); } - ZeroMemory(&dm, sizeof(dm)); - dm.dmSize = sizeof(dm); - EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm); - rect.left = dm.dmPosition.x; rect.top = dm.dmPosition.y; rect.right = dm.dmPosition.x + dm.dmPelsWidth; @@ -302,6 +312,26 @@ void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor) } } +void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale) +{ + UINT xdpi, ydpi; + + if (IsWindows8Point1OrGreater()) + GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); + else + { + const HDC dc = GetDC(NULL); + xdpi = GetDeviceCaps(dc, LOGPIXELSX); + ydpi = GetDeviceCaps(dc, LOGPIXELSY); + ReleaseDC(NULL, dc); + } + + if (xscale) + *xscale = xdpi / 96.f; + if (yscale) + *yscale = ydpi / 96.f; +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// @@ -324,6 +354,12 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) *ypos = dm.dmPosition.y; } +void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, + float* xscale, float* yscale) +{ + _glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale); +} + GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) { int modeIndex = 0, size = 0; diff --git a/src/win32_platform.h b/src/win32_platform.h index acbb5ca2..1bfc638f 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -135,6 +135,13 @@ typedef enum PROCESS_DPI_AWARENESS PROCESS_SYSTEM_DPI_AWARE = 1, PROCESS_PER_MONITOR_DPI_AWARE = 2 } PROCESS_DPI_AWARENESS; +typedef enum MONITOR_DPI_TYPE +{ + MDT_EFFECTIVE_DPI = 0, + MDT_ANGULAR_DPI = 1, + MDT_RAW_DPI = 2, + MDT_DEFAULT = MDT_EFFECTIVE_DPI +} MONITOR_DPI_TYPE; #endif /*DPI_ENUMS_DECLARED*/ // HACK: Define versionhelpers.h functions manually as MinGW lacks the header @@ -216,7 +223,9 @@ typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIN // shcore.dll function pointer typedefs typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); +typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*); #define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_ +#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_ typedef VkFlags VkWin32SurfaceCreateFlagsKHR; @@ -326,6 +335,7 @@ typedef struct _GLFWlibraryWin32 struct { HINSTANCE instance; PFN_SetProcessDpiAwareness SetProcessDpiAwareness_; + PFN_GetDpiForMonitor GetDpiForMonitor_; } shcore; } _GLFWlibraryWin32; @@ -395,4 +405,5 @@ void _glfwInitTimerWin32(void); void _glfwPollMonitorsWin32(void); GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired); void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor); +void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale); diff --git a/src/win32_window.c b/src/win32_window.c index 490a75d2..394a24da 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -983,19 +983,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, break; } - case WM_DPICHANGED: - { - RECT* rect = (RECT*) lParam; - SetWindowPos(window->win32.handle, - HWND_TOP, - rect->left, - rect->top, - rect->right - rect->left, - rect->bottom - rect->top, - SWP_NOACTIVATE | SWP_NOZORDER); - break; - } - case WM_DROPFILES: { HDROP drop = (HDROP) wParam; @@ -1415,6 +1402,14 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, *bottom = rect.bottom - height; } +void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, + float* xscale, float* yscale) +{ + const HANDLE handle = MonitorFromWindow(window->win32.handle, + MONITOR_DEFAULTTONEAREST); + _glfwGetMonitorContentScaleWin32(handle, xscale, yscale); +} + void _glfwPlatformIconifyWindow(_GLFWwindow* window) { ShowWindow(window->win32.handle, SW_MINIMIZE); diff --git a/src/window.c b/src/window.c index 57845579..c91ef005 100644 --- a/src/window.c +++ b/src/window.c @@ -632,6 +632,21 @@ GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle, _glfwPlatformGetWindowFrameSize(window, left, top, right, bottom); } +GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle, + float* xscale, float* yscale) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + + if (xscale) + *xscale = 0.f; + if (yscale) + *yscale = 0.f; + + _GLFW_REQUIRE_INIT(); + _glfwPlatformGetWindowContentScale(window, xscale, yscale); +} + GLFWAPI void glfwIconifyWindow(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; diff --git a/src/wl_monitor.c b/src/wl_monitor.c index 24b0b39a..10ef0e12 100644 --- a/src/wl_monitor.c +++ b/src/wl_monitor.c @@ -153,6 +153,15 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) *ypos = monitor->wl.y; } +void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, + float* xscale, float* yscale) +{ + if (xscale) + *xscale = (float) monitor->wl.scale; + if (yscale) + *yscale = (float) monitor->wl.scale; +} + GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) { *found = monitor->modeCount; diff --git a/src/wl_window.c b/src/wl_window.c index 32d5f404..649ed7e9 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -550,6 +550,15 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, // implemented, but for now just leave everything as 0. } +void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, + float* xscale, float* yscale) +{ + if (xscale) + *xscale = (float) window->wl.scale; + if (yscale) + *yscale = (float) window->wl.scale; +} + void _glfwPlatformIconifyWindow(_GLFWwindow* window) { // TODO: move to xdg_shell instead of wl_shell. diff --git a/src/x11_init.c b/src/x11_init.c index 526d9ca2..b603a15f 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -743,6 +743,43 @@ static GLFWbool initExtensions(void) return GLFW_TRUE; } +// Retrieve system content scale via folklore heuristics +// +static void getSystemContentScale(float* xscale, float* yscale) +{ + // NOTE: Default to the display-wide DPI as we don't currently have a policy + // for which monitor a window is considered to be on + float xdpi = DisplayWidth(_glfw.x11.display, _glfw.x11.screen) * + 25.4f / DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen); + float ydpi = DisplayHeight(_glfw.x11.display, _glfw.x11.screen) * + 25.4f / DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen); + + // NOTE: Basing the scale on Xft.dpi where available should provide the most + // consistent user experience (matches Qt, Gtk, etc), although not + // always the most accurate one + char* rms = XResourceManagerString(_glfw.x11.display); + if (rms) + { + XrmDatabase db = XrmGetStringDatabase(rms); + if (db) + { + XrmValue value; + char* type = NULL; + + if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value)) + { + if (type && strcmp(type, "String") == 0) + xdpi = ydpi = atof(value.addr); + } + + XrmDestroyDatabase(db); + } + } + + *xscale = xdpi / 96.f; + *yscale = ydpi / 96.f; +} + // Create a blank cursor for hidden and disabled cursor modes // static Cursor createHiddenCursor(void) @@ -861,6 +898,7 @@ int _glfwPlatformInit(void) #endif XInitThreads(); + XrmInitialize(); _glfw.x11.display = XOpenDisplay(NULL); if (!_glfw.x11.display) @@ -884,6 +922,8 @@ int _glfwPlatformInit(void) _glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen); _glfw.x11.context = XUniqueContext(); + getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY); + if (!initExtensions()) return GLFW_FALSE; diff --git a/src/x11_monitor.c b/src/x11_monitor.c index 5c0516e6..d68c5888 100644 --- a/src/x11_monitor.c +++ b/src/x11_monitor.c @@ -338,6 +338,15 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) } } +void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, + float* xscale, float* yscale) +{ + if (xscale) + *xscale = _glfw.x11.contentScaleX; + if (yscale) + *yscale = _glfw.x11.contentScaleY; +} + GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) { GLFWvidmode* result; diff --git a/src/x11_platform.h b/src/x11_platform.h index 2b1c0c62..7eba441d 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -211,6 +211,8 @@ typedef struct _GLFWlibraryX11 int screen; Window root; + // System content scale + float contentScaleX, contentScaleY; // Helper window for IPC Window helperWindowHandle; // Invisible cursor for hidden cursor mode diff --git a/src/x11_window.c b/src/x11_window.c index cf5483b0..7c407cc5 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2240,6 +2240,15 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, XFree(extents); } +void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, + float* xscale, float* yscale) +{ + if (xscale) + *xscale = _glfw.x11.contentScaleX; + if (yscale) + *yscale = _glfw.x11.contentScaleY; +} + void _glfwPlatformIconifyWindow(_GLFWwindow* window) { if (window->x11.overrideRedirect) diff --git a/tests/monitors.c b/tests/monitors.c index fc54c319..c7fd5c5c 100644 --- a/tests/monitors.c +++ b/tests/monitors.c @@ -92,21 +92,24 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action, static void list_modes(GLFWmonitor* monitor) { - int count, x, y, widthMM, heightMM, i; + int count, x, y, width_mm, height_mm, i; + float xscale, yscale; const GLFWvidmode* mode = glfwGetVideoMode(monitor); const GLFWvidmode* modes = glfwGetVideoModes(monitor, &count); glfwGetMonitorPos(monitor, &x, &y); - glfwGetMonitorPhysicalSize(monitor, &widthMM, &heightMM); + glfwGetMonitorPhysicalSize(monitor, &width_mm, &height_mm); + glfwGetMonitorContentScale(monitor, &xscale, &yscale); printf("Name: %s (%s)\n", glfwGetMonitorName(monitor), glfwGetPrimaryMonitor() == monitor ? "primary" : "secondary"); printf("Current mode: %s\n", format_mode(mode)); printf("Virtual position: %i %i\n", x, y); + printf("Content scale: %f %f\n", xscale, yscale); printf("Physical size: %i x %i mm (%0.2f dpi)\n", - widthMM, heightMM, mode->width * 25.4f / widthMM); + width_mm, height_mm, mode->width * 25.4f / width_mm); printf("Modes:\n"); From bf09dba95b92637795ef6f13ad87f1c9a2e5b0be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 26 Oct 2017 18:05:56 +0200 Subject: [PATCH 06/12] Cleanup --- src/cocoa_window.m | 2 +- src/internal.h | 2 +- src/win32_window.c | 2 +- src/window.c | 2 +- src/wl_window.c | 2 +- src/x11_window.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 4c9dea90..1ee85bc6 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1375,7 +1375,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, if (window->monitor) releaseMonitor(window); - _glfwInputWindowMonitorChange(window, monitor); + _glfwInputWindowMonitor(window, monitor); // HACK: Allow the state cached in Cocoa to catch up to reality // TODO: Solve this in a less terrible way diff --git a/src/internal.h b/src/internal.h index 39494340..1bfdb859 100644 --- a/src/internal.h +++ b/src/internal.h @@ -779,7 +779,7 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window); * @param[in] monitor The new desired monitor, or `NULL`. * @ingroup event */ -void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor); +void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor); /*! @brief Notifies shared code of a physical key event. * @param[in] window The window that received the event. diff --git a/src/win32_window.c b/src/win32_window.c index 394a24da..71738d14 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -1477,7 +1477,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, if (window->monitor) releaseMonitor(window); - _glfwInputWindowMonitorChange(window, monitor); + _glfwInputWindowMonitor(window, monitor); if (monitor) { diff --git a/src/window.c b/src/window.c index c91ef005..0e1c2484 100644 --- a/src/window.c +++ b/src/window.c @@ -108,7 +108,7 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window) window->callbacks.close((GLFWwindow*) window); } -void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor) +void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor) { window->monitor = monitor; } diff --git a/src/wl_window.c b/src/wl_window.c index 649ed7e9..f0f2637e 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -642,7 +642,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, { wl_shell_surface_set_toplevel(window->wl.shellSurface); } - _glfwInputWindowMonitorChange(window, monitor); + _glfwInputWindowMonitor(window, monitor); } int _glfwPlatformWindowFocused(_GLFWwindow* window) diff --git a/src/x11_window.c b/src/x11_window.c index 7c407cc5..c89d2ec5 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2377,7 +2377,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, if (window->monitor) releaseMonitor(window); - _glfwInputWindowMonitorChange(window, monitor); + _glfwInputWindowMonitor(window, monitor); updateNormalHints(window, width, height); updateWindowMode(window); From fcedb0be325425a6ad16d53349f2008ac4fc05d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 26 Oct 2017 18:52:43 +0200 Subject: [PATCH 07/12] Fix windows not detaching on monitor disconnect Regression introduced by 04f559e28d02f621187a0631490f26527cee8b81. Related to #1106. --- src/monitor.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/monitor.c b/src/monitor.c index 40b24132..0dfb1958 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -107,6 +107,17 @@ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement) else if (action == GLFW_DISCONNECTED) { int i; + _GLFWwindow* window; + + for (window = _glfw.windowListHead; window; window = window->next) + { + if (window->monitor == monitor) + { + int width, height; + _glfwPlatformGetWindowSize(window, &width, &height); + _glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0); + } + } for (i = 0; i < _glfw.monitorCount; i++) { From a1154247fad6ebd1e109e4cdbc32b93266646835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 29 Oct 2017 15:52:22 +0100 Subject: [PATCH 08/12] Fix default value of GLFW_CENTER_CURSOR Regression introduced by 72ac5badb0a188b0d912b1e4fa79a5e143253474. Fixes #1105. --- src/window.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/window.c b/src/window.c index 0e1c2484..30321733 100644 --- a/src/window.c +++ b/src/window.c @@ -246,11 +246,12 @@ void glfwDefaultWindowHints(void) // The default is a focused, visible, resizable window with decorations memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window)); - _glfw.hints.window.resizable = GLFW_TRUE; - _glfw.hints.window.visible = GLFW_TRUE; - _glfw.hints.window.decorated = GLFW_TRUE; - _glfw.hints.window.focused = GLFW_TRUE; - _glfw.hints.window.autoIconify = GLFW_TRUE; + _glfw.hints.window.resizable = GLFW_TRUE; + _glfw.hints.window.visible = GLFW_TRUE; + _glfw.hints.window.decorated = GLFW_TRUE; + _glfw.hints.window.focused = GLFW_TRUE; + _glfw.hints.window.autoIconify = GLFW_TRUE; + _glfw.hints.window.centerCursor = GLFW_TRUE; // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil, // double buffered From 2867ca1e5b003b167fac33e8136a4698bb3aa074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 29 Oct 2017 16:27:15 +0100 Subject: [PATCH 09/12] Documentation work Fixes #1104. --- docs/window.dox | 14 +++++++------- include/GLFW/glfw3.h | 5 +++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/window.dox b/docs/window.dox index 7961e028..f2146502 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -582,15 +582,15 @@ window's desired video mode. The video mode most closely matching the new desired video mode is set immediately. The window is resized to fit the resolution of the set video mode. -If you wish to be notified when a window is resized, whether by the user or -the system, set a size callback. +If you wish to be notified when a window is resized, whether by the user, the +system or your own code, set a size callback. @code glfwSetWindowSizeCallback(window, window_size_callback); @endcode The callback function receives the new size, in screen coordinates, of the -client area of the window when it is resized. +client area of the window when the window is resized. @code void window_size_callback(GLFWwindow* window, int width, int height) @@ -740,15 +740,15 @@ The window system may put limitations on window placement. glfwSetWindowPos(window, 100, 100); @endcode -If you wish to be notified when a window is moved, whether by the user, system -or your own code, set a position callback. +If you wish to be notified when a window is moved, whether by the user, the +system or your own code, set a position callback. @code glfwSetWindowPosCallback(window, window_pos_callback); @endcode -The callback function receives the new position of the upper-left corner of the -client area when the window is moved. +The callback function receives the new position, in screen coordinates, of the +upper-left corner of the client area when the window is moved. @code void window_pos_callback(GLFWwindow* window, int xpos, int ypos) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 0ba409b0..6923ba68 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -3220,8 +3220,9 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window); /*! @brief Sets the position callback for the specified window. * * This function sets the position callback of the specified window, which is - * called when the window is moved. The callback is provided with the screen - * position of the upper-left corner of the client area of the window. + * called when the window is moved. The callback is provided with the + * position, in screen coordinates, of the upper-left corner of the client area + * of the window. * * @param[in] window The window whose callback to set. * @param[in] cbfun The new callback, or `NULL` to remove the currently set From a7a70cf34de16b8a0395551f69d429a7b6148ba4 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sat, 26 Aug 2017 19:25:24 +0100 Subject: [PATCH 10/12] Wayland: Add dynamic loading of libxkbcommon --- CMakeLists.txt | 2 -- src/wl_init.c | 46 ++++++++++++++++++++++++++++++++++++++++ src/wl_platform.h | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 56c1f386..239a8bfc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -286,9 +286,7 @@ if (_GLFW_WAYLAND) list(APPEND glfw_LIBRARIES "${Wayland_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}") find_package(XKBCommon REQUIRED) - list(APPEND glfw_PKG_DEPS "xkbcommon") list(APPEND glfw_INCLUDE_DIRS "${XKBCOMMON_INCLUDE_DIRS}") - list(APPEND glfw_LIBRARIES "${XKBCOMMON_LIBRARY}") endif() #-------------------------------------------------------------------- diff --git a/src/wl_init.c b/src/wl_init.c index 8e42ce6e..3841636f 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -642,6 +642,49 @@ static void createKeyTables(void) int _glfwPlatformInit(void) { + _glfw.wl.xkb.handle = dlopen("libxkbcommon.so.0", RTLD_LAZY | RTLD_GLOBAL); + if (!_glfw.wl.xkb.handle) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to open libxkbcommon."); + return GLFW_FALSE; + } + + _glfw.wl.xkb.context_new = (PFN_xkb_context_new) + dlsym(_glfw.wl.xkb.handle, "xkb_context_new"); + _glfw.wl.xkb.context_unref = (PFN_xkb_context_unref) + dlsym(_glfw.wl.xkb.handle, "xkb_context_unref"); + _glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string) + dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string"); + _glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref) + dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref"); + _glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index) + dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index"); + _glfw.wl.xkb.state_new = (PFN_xkb_state_new) + dlsym(_glfw.wl.xkb.handle, "xkb_state_new"); + _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref) + dlsym(_glfw.wl.xkb.handle, "xkb_state_unref"); + _glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms) + dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms"); + _glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask) + dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask"); + _glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods) + dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods"); + _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale) + dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale"); + _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref) + dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref"); + _glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new) + dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new"); + _glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref) + dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref"); + _glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed) + dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed"); + _glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status) + dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status"); + _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym) + dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym"); + _glfw.wl.display = wl_display_connect(NULL); if (!_glfw.wl.display) { @@ -700,6 +743,9 @@ void _glfwPlatformTerminate(void) xkb_state_unref(_glfw.wl.xkb.state); xkb_context_unref(_glfw.wl.xkb.context); + dlclose(_glfw.wl.xkb.handle); + _glfw.wl.xkb.handle = NULL; + if (_glfw.wl.cursorTheme) wl_cursor_theme_destroy(_glfw.wl.cursorTheme); if (_glfw.wl.cursorSurface) diff --git a/src/wl_platform.h b/src/wl_platform.h index 656f0ef1..059ea2ee 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -68,6 +68,41 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR #define _GLFW_PLATFORM_CONTEXT_STATE #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE +typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags); +typedef void (* PFN_xkb_context_unref)(struct xkb_context*); +typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags); +typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*); +typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*); +typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*); +typedef void (* PFN_xkb_state_unref)(struct xkb_state*); +typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**); +typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t); +typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component); +typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags); +typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*); +typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags); +typedef void (* PFN_xkb_compose_state_unref)(struct xkb_compose_state*); +typedef enum xkb_compose_feed_result (* PFN_xkb_compose_state_feed)(struct xkb_compose_state*, xkb_keysym_t); +typedef enum xkb_compose_status (* PFN_xkb_compose_state_get_status)(struct xkb_compose_state*); +typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_state*); +#define xkb_context_new _glfw.wl.xkb.context_new +#define xkb_context_unref _glfw.wl.xkb.context_unref +#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string +#define xkb_keymap_unref _glfw.wl.xkb.keymap_unref +#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index +#define xkb_state_new _glfw.wl.xkb.state_new +#define xkb_state_unref _glfw.wl.xkb.state_unref +#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms +#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask +#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods +#define xkb_compose_table_new_from_locale _glfw.wl.xkb.compose_table_new_from_locale +#define xkb_compose_table_unref _glfw.wl.xkb.compose_table_unref +#define xkb_compose_state_new _glfw.wl.xkb.compose_state_new +#define xkb_compose_state_unref _glfw.wl.xkb.compose_state_unref +#define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed +#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status +#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym + // Wayland-specific per-window data // @@ -125,6 +160,7 @@ typedef struct _GLFWlibraryWayland short int scancodes[GLFW_KEY_LAST + 1]; struct { + void* handle; struct xkb_context* context; struct xkb_keymap* keymap; struct xkb_state* state; @@ -134,6 +170,24 @@ typedef struct _GLFWlibraryWayland xkb_mod_mask_t shiftMask; xkb_mod_mask_t superMask; unsigned int modifiers; + + PFN_xkb_context_new context_new; + PFN_xkb_context_unref context_unref; + PFN_xkb_keymap_new_from_string keymap_new_from_string; + PFN_xkb_keymap_unref keymap_unref; + PFN_xkb_keymap_mod_get_index keymap_mod_get_index; + PFN_xkb_state_new state_new; + PFN_xkb_state_unref state_unref; + PFN_xkb_state_key_get_syms state_key_get_syms; + PFN_xkb_state_update_mask state_update_mask; + PFN_xkb_state_serialize_mods state_serialize_mods; + PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale; + PFN_xkb_compose_table_unref compose_table_unref; + PFN_xkb_compose_state_new compose_state_new; + PFN_xkb_compose_state_unref compose_state_unref; + PFN_xkb_compose_state_feed compose_state_feed; + PFN_xkb_compose_state_get_status compose_state_get_status; + PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym; } xkb; _GLFWwindow* pointerFocus; From 80d181f12dbb3b19fa649638252fa90eacf3d6a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 31 Oct 2017 15:47:01 +0100 Subject: [PATCH 11/12] Win32: Fix maximization of undecorated windows Fixes #899. --- README.md | 1 + src/win32_window.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/README.md b/README.md index a890ac09..4048baf1 100644 --- a/README.md +++ b/README.md @@ -200,6 +200,7 @@ information on what to include when reporting a bug. - [Win32] Bugfix: Disabled cursor mode prevented use of caption buttons (#650,#1071) - [Win32] Bugfix: Returned key names did not match other platforms (#943) +- [Win32] Bugfix: Undecorated windows did not maximize to workarea (#899) - [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125) - [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading - [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X diff --git a/src/win32_window.c b/src/win32_window.c index 71738d14..6d3e76cc 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -951,6 +951,22 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, mmi->ptMaxTrackSize.y = window->maxheight + yoff; } + if (!window->decorated) + { + MONITORINFO mi; + const HMONITOR mh = MonitorFromWindow(window->win32.handle, + MONITOR_DEFAULTTONEAREST); + + ZeroMemory(&mi, sizeof(mi)); + mi.cbSize = sizeof(mi); + GetMonitorInfo(mh, &mi); + + mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left; + mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top; + mmi->ptMaxSize.x = mi.rcWork.right - mi.rcWork.left; + mmi->ptMaxSize.y = mi.rcWork.bottom - mi.rcWork.top; + } + return 0; } From 9718675d86fe2013c7b5965ff394391f24df02ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 1 Nov 2017 21:32:50 +0100 Subject: [PATCH 12/12] Documentation work Related to #1106. --- docs/monitor.dox | 4 ++-- docs/window.dox | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/monitor.dox b/docs/monitor.dox index 7245f70c..620646d5 100644 --- a/docs/monitor.dox +++ b/docs/monitor.dox @@ -85,8 +85,8 @@ void monitor_callback(GLFWmonitor* monitor, int event) } @endcode -If a monitor is disconnected, any windows that are full screen on it get forced -into windowed mode. +If a monitor is disconnected, all windows that are full screen on it will be +switched to windowed mode. @section monitor_properties Monitor properties diff --git a/docs/window.dox b/docs/window.dox index f2146502..3e8c748f 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -89,8 +89,8 @@ the desktop. This behavior can be disabled with the [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_hint) window hint, for example if you wish to simultaneously cover multiple monitors with full screen windows. -If a monitor is disconnected, any window that is full screen on that monitor -will be forced into windowed mode. See @ref monitor_event for more information. +If a monitor is disconnected, all windows that are full screen on that monitor +will be switched to windowed mode. See @ref monitor_event for more information. @subsubsection window_windowed_full_screen "Windowed full screen" windows