diff --git a/.gitignore b/.gitignore index 428e7334..266019f3 100644 --- a/.gitignore +++ b/.gitignore @@ -100,5 +100,6 @@ tests/threads tests/timeout tests/title tests/triangle-vulkan +tests/window tests/windows diff --git a/.travis.yml b/.travis.yml index bc924a90..c5978469 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ matrix: - libxinerama-dev - libxcursor-dev - libxi-dev + - libxext-dev env: - BUILD_SHARED_LIBS=ON - CFLAGS=-Werror @@ -30,18 +31,18 @@ matrix: - libxinerama-dev - libxcursor-dev - libxi-dev + - libxext-dev env: - BUILD_SHARED_LIBS=OFF - CFLAGS=-Werror - os: linux - dist: xenial + dist: focal name: "Wayland shared library" addons: apt: - sources: - - ppa:kubuntu-ppa/backports packages: - extra-cmake-modules + - wayland-protocols - libwayland-dev - libxkbcommon-dev - libegl1-mesa-dev @@ -50,14 +51,13 @@ matrix: - BUILD_SHARED_LIBS=ON - CFLAGS=-Werror - os: linux - dist: xenial + dist: focal name: "Wayland static library" addons: apt: - sources: - - ppa:kubuntu-ppa/backports packages: - extra-cmake-modules + - wayland-protocols - libwayland-dev - libxkbcommon-dev - libegl1-mesa-dev @@ -106,12 +106,6 @@ script: fi - mkdir build - cd build - - if test -n "${USE_WAYLAND}"; then - git clone git://anongit.freedesktop.org/wayland/wayland-protocols; - pushd wayland-protocols; - git checkout 1.15 && ./autogen.sh --prefix=/usr && make && sudo make install; - popd; - fi - cmake -DCMAKE_VERBOSE_MAKEFILE=ON -DBUILD_SHARED_LIBS=${BUILD_SHARED_LIBS} -DGLFW_USE_WAYLAND=${USE_WAYLAND} -DGLFW_USE_OSMESA=${USE_OSMESA} .. - cmake --build . notifications: diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f7ad4ca..a3a884b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,10 @@ if (POLICY CMP0054) cmake_policy(SET CMP0054 NEW) endif() +if (POLICY CMP0069) + cmake_policy(SET CMP0069 NEW) +endif() + if (POLICY CMP0077) cmake_policy(SET CMP0077 NEW) endif() @@ -176,6 +180,11 @@ if (_GLFW_X11) if (NOT X11_Xi_INCLUDE_PATH) message(FATAL_ERROR "XInput headers not found; install libxi development package") endif() + + # Check for X Shape (custom window input shape) + if (NOT X11_Xshape_INCLUDE_PATH) + message(FATAL_ERROR "X Shape headers not found; install libxext development package") + endif() endif() #-------------------------------------------------------------------- diff --git a/README.md b/README.md index e6440d51..0fde759f 100644 --- a/README.md +++ b/README.md @@ -124,10 +124,13 @@ information on what to include when reporting a bug. - Added `GLFW_RESIZE_EW_CURSOR` alias for `GLFW_HRESIZE_CURSOR` (#427) - Added `GLFW_RESIZE_NS_CURSOR` alias for `GLFW_VRESIZE_CURSOR` (#427) - Added `GLFW_POINTING_HAND_CURSOR` alias for `GLFW_HAND_CURSOR` (#427) + - Added `GLFW_MOUSE_PASSTHROUGH` window hint for letting mouse input pass + through the window (#1236,#1568) - Added `GLFW_FEATURE_UNAVAILABLE` error for platform limitations (#1692) - Added `GLFW_FEATURE_UNIMPLEMENTED` error for incomplete backends (#1692) - Added `GLFW_ANGLE_PLATFORM_TYPE` init hint and `GLFW_ANGLE_PLATFORM_TYPE_*` values to select ANGLE backend (#1380) + - Made joystick subsystem initialize at first use (#1284,#1646) - Updated the minimum required CMake version to 3.1 - Disabled tests and examples by default when built as a CMake subdirectory - Bugfix: The CMake config-file package used an absolute path and was not @@ -140,6 +143,8 @@ information on what to include when reporting a bug. - [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access to the window menu - [Win32] Added a version info resource to the GLFW DLL + - [Win32] Disabled framebuffer transparency on Windows 7 when DWM windows are + opaque (#1512) - [Win32] Bugfix: `GLFW_INCLUDE_VULKAN` plus `VK_USE_PLATFORM_WIN32_KHR` caused symbol redefinition (#1524) - [Win32] Bugfix: The cursor position event was emitted before its cursor enter @@ -167,6 +172,8 @@ information on what to include when reporting a bug. would abort (#1649) - [Cocoa] Bugfix: Non-BMP Unicode codepoint input was reported as UTF-16 (#1635) + - [Cocoa] Bugfix: Failing to retrieve the refresh rate of built-in displays + could leak memory - [X11] Bugfix: The CMake files did not check for the XInput headers (#1480) - [X11] Bugfix: Key names were not updated when the keyboard layout changed (#1462,#1528) @@ -196,12 +203,16 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432) - [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled - [Wayland] Bugfix: Repeated keys could be reported with `NULL` window (#1704) + - [Wayland] Bugfix: Retrieving partial framebuffer size would segfault + - [Wayland] Bugfix: Scrolling offsets were inverted compared to other platforms + (#1463) - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [NSGL] Removed enforcement of forward-compatible flag for core contexts - [NSGL] Bugfix: `GLFW_COCOA_RETINA_FRAMEBUFFER` had no effect on newer macOS versions (#1442) - [NSGL] Bugfix: Workaround for swap interval on 10.14 broke on 10.12 (#1483) - [EGL] Added platform selection via the `EGL_EXT_platform_base` extension + (#442) - [EGL] Added ANGLE backend selection via `EGL_ANGLE_platform_angle` extension (#1380) @@ -342,6 +353,7 @@ skills. - ndogxj - Kristian Nielsen - Kamil Nowakowski + - onox - Denis Ovod - Ozzy - Andri Pálsson diff --git a/deps/nuklear.h b/deps/nuklear.h index 6c873535..f2eb9dfa 100644 --- a/deps/nuklear.h +++ b/deps/nuklear.h @@ -105,6 +105,8 @@ /// NK_INCLUDE_COMMAND_USERDATA | Defining this adds a userdata pointer into each command. Can be useful for example if you want to provide custom shaders depending on the used widget. Can be combined with the style structures. /// NK_BUTTON_TRIGGER_ON_RELEASE | Different platforms require button clicks occurring either on buttons being pressed (up to down) or released (down to up). By default this library will react on buttons being pressed, but if you define this it will only trigger if a button is released. /// NK_ZERO_COMMAND_MEMORY | Defining this will zero out memory for each drawing command added to a drawing queue (inside nk_command_buffer_push). Zeroing command memory is very useful for fast checking (using memcmp) if command buffers are equal and avoid drawing frames when nothing on screen has changed since previous frame. +/// NK_UINT_DRAW_INDEX | Defining this will set the size of vertex index elements when using NK_VERTEX_BUFFER_OUTPUT to 32bit instead of the default of 16bit +/// NK_KEYSTATE_BASED_INPUT | Define this if your backend uses key state for each frame rather than key press/release events /// /// !!! WARNING /// The following flags will pull in the standard C library: @@ -122,6 +124,7 @@ /// - NK_INCLUDE_DEFAULT_FONT /// - NK_INCLUDE_STANDARD_VARARGS /// - NK_INCLUDE_COMMAND_USERDATA +/// - NK_UINT_DRAW_INDEX /// /// ### Constants /// Define | Description @@ -301,6 +304,7 @@ extern "C" { #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i)) #ifdef NK_INCLUDE_STANDARD_VARARGS + #include /* valist, va_start, va_end, ... */ #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */ #include #define NK_PRINTF_FORMAT_STRING _Printf_format_string_ @@ -314,7 +318,6 @@ extern "C" { #define NK_PRINTF_VARARG_FUNC(fmtargnumber) #define NK_PRINTF_VALIST_FUNC(fmtargnumber) #endif - #include /* valist, va_start, va_end, ... */ #endif /* @@ -336,7 +339,7 @@ extern "C" { #define NK_POINTER_TYPE uintptr_t #else #ifndef NK_INT8 - #define NK_INT8 char + #define NK_INT8 signed char #endif #ifndef NK_UINT8 #define NK_UINT8 unsigned char @@ -1084,6 +1087,12 @@ NK_API void nk_input_end(struct nk_context*); /// /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c /// // fill configuration +/// struct your_vertex +/// { +/// float pos[2]; // important to keep it to 2 floats +/// float uv[2]; +/// unsigned char col[4]; +/// }; /// struct nk_convert_config cfg = {}; /// static const struct nk_draw_vertex_layout_element vertex_layout[] = { /// {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)}, @@ -1209,7 +1218,7 @@ NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_com /// /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c /// nk_flags nk_convert(struct nk_context *ctx, struct nk_buffer *cmds, -// struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*); +/// struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*); /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /// /// Parameter | Description @@ -1394,6 +1403,7 @@ NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command* /// nk_window_get_content_region_max | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window /// nk_window_get_content_region_size | Returns the size of the currently visible and non-clipped space inside the currently processed window /// nk_window_get_canvas | Returns the draw command buffer. Can be used to draw custom widgets +/// nk_window_get_scroll | Gets the scroll offset of the current window /// nk_window_has_focus | Returns if the currently processed window is currently active /// nk_window_is_collapsed | Returns if the window with given name is currently minimized/collapsed /// nk_window_is_closed | Returns if the currently processed window was closed @@ -1407,6 +1417,7 @@ NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command* /// nk_window_set_position | Updates position of the currently process window /// nk_window_set_size | Updates the size of the currently processed window /// nk_window_set_focus | Set the currently processed window as active window +/// nk_window_set_scroll | Sets the scroll offset of the current window // /// nk_window_close | Closes the window with given window name which deletes the window at the end of the frame /// nk_window_collapse | Collapses the window with given window name @@ -1427,7 +1438,7 @@ NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command* /// NK_WINDOW_TITLE | Forces a header at the top at the window showing the title /// NK_WINDOW_SCROLL_AUTO_HIDE | Automatically hides the window scrollbar if no user interaction: also requires delta time in `nk_context` to be set each frame /// NK_WINDOW_BACKGROUND | Always keep window in the background -/// NK_WINDOW_SCALE_LEFT | Puts window scaler in the left-ottom corner instead right-bottom +/// NK_WINDOW_SCALE_LEFT | Puts window scaler in the left-bottom corner instead right-bottom /// NK_WINDOW_NO_INPUT | Prevents window of scaling, moving or getting focus /// /// #### nk_collapse_states @@ -1506,7 +1517,7 @@ NK_API void nk_end(struct nk_context *ctx); /// Finds and returns a window from passed name /// /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c -/// void nk_end(struct nk_context *ctx); +/// struct nk_window *nk_window_find(struct nk_context *ctx, const char *name); /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /// /// Parameter | Description @@ -1710,6 +1721,22 @@ NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context*); /// drawing canvas. Can be used to do custom drawing. */ NK_API struct nk_command_buffer* nk_window_get_canvas(struct nk_context*); +/*/// #### nk_window_get_scroll +/// Gets the scroll offset for the current window +/// !!! WARNING +/// Only call this function between calls `nk_begin_xxx` and `nk_end` +/// +/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c +/// void nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y); +/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/// +/// Parameter | Description +/// -------------|----------------------------------------------------------- +/// __ctx__ | Must point to an previously initialized `nk_context` struct +/// __offset_x__ | A pointer to the x offset output (or NULL to ignore) +/// __offset_y__ | A pointer to the y offset output (or NULL to ignore) +*/ +NK_API void nk_window_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y); /*/// #### nk_window_has_focus /// Returns if the currently processed window is currently active /// !!! WARNING @@ -1876,6 +1903,22 @@ NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_v /// __name__ | Identifier of the window to set focus on */ NK_API void nk_window_set_focus(struct nk_context*, const char *name); +/*/// #### nk_window_set_scroll +/// Sets the scroll offset for the current window +/// !!! WARNING +/// Only call this function between calls `nk_begin_xxx` and `nk_end` +/// +/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c +/// void nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y); +/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/// +/// Parameter | Description +/// -------------|----------------------------------------------------------- +/// __ctx__ | Must point to an previously initialized `nk_context` struct +/// __offset_x__ | The x offset to scroll to +/// __offset_y__ | The y offset to scroll to +*/ +NK_API void nk_window_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y); /*/// #### nk_window_close /// Closes a window and marks it for being freed at the end of the frame /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c @@ -2588,7 +2631,7 @@ NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct n /// case ...: /// // [...] /// } -// nk_clear(&ctx); +/// nk_clear(&ctx); /// } /// nk_free(&ctx); /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2601,6 +2644,8 @@ NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct n /// nk_group_scrolled_offset_begin | Start a new group with manual separated handling of scrollbar x- and y-offset /// nk_group_scrolled_begin | Start a new group with manual scrollbar handling /// nk_group_scrolled_end | Ends a group with manual scrollbar handling. Should only be called if nk_group_begin returned non-zero +/// nk_group_get_scroll | Gets the scroll offset for the given group +/// nk_group_set_scroll | Sets the scroll offset for the given group */ /*/// #### nk_group_begin /// Starts a new widget group. Requires a previous layouting function to specify a pos/size. @@ -2690,11 +2735,39 @@ NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, co /// __ctx__ | Must point to an previously initialized `nk_context` struct */ NK_API void nk_group_scrolled_end(struct nk_context*); +/*/// #### nk_group_get_scroll +/// Gets the scroll position of the given group. +/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c +/// void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset); +/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/// +/// Parameter | Description +/// -------------|----------------------------------------------------------- +/// __ctx__ | Must point to an previously initialized `nk_context` struct +/// __id__ | The id of the group to get the scroll position of +/// __x_offset__ | A pointer to the x offset output (or NULL to ignore) +/// __y_offset__ | A pointer to the y offset output (or NULL to ignore) +*/ +NK_API void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset); +/*/// #### nk_group_set_scroll +/// Sets the scroll position of the given group. +/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c +/// void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset); +/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +/// +/// Parameter | Description +/// -------------|----------------------------------------------------------- +/// __ctx__ | Must point to an previously initialized `nk_context` struct +/// __id__ | The id of the group to scroll +/// __x_offset__ | The x offset to scroll to +/// __y_offset__ | The y offset to scroll to +*/ +NK_API void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset); /* ============================================================================= * * TREE * - * ============================================================================= + * ============================================================================= /// ### Tree /// Trees represent two different concept. First the concept of a collapsable /// UI section that can be either in a hidden or visibile state. They allow the UI @@ -3187,7 +3260,7 @@ NK_API int nk_color_pick(struct nk_context*, struct nk_colorf*, enum nk_color_fo /// case ...: /// // [...] /// } -// nk_clear(&ctx); +/// nk_clear(&ctx); /// } /// nk_free(&ctx); /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -3395,6 +3468,8 @@ NK_API void nk_plot_function(struct nk_context*, enum nk_chart_type, void *userd NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds); NK_API void nk_popup_close(struct nk_context*); NK_API void nk_popup_end(struct nk_context*); +NK_API void nk_popup_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y); +NK_API void nk_popup_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y); /* ============================================================================= * * COMBOBOX @@ -4588,7 +4663,11 @@ NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys); In fact it is probably more powerful than needed but allows even more crazy things than this library provides by default. */ +#ifdef NK_UINT_DRAW_INDEX +typedef nk_uint nk_draw_index; +#else typedef nk_ushort nk_draw_index; +#endif enum nk_draw_list_stroke { NK_STROKE_OPEN = nk_false, /* build up path has no connection back to the beginning */ @@ -5603,7 +5682,6 @@ template struct nk_alignof{struct Big {T x; char c;}; enum { #endif /* NK_NUKLEAR_H_ */ - #ifdef NK_IMPLEMENTATION #ifndef NK_INTERNAL_H @@ -6007,15 +6085,18 @@ nk_sin(float x) NK_LIB float nk_cos(float x) { - NK_STORAGE const float a0 = +1.00238601909309722f; - NK_STORAGE const float a1 = -3.81919947353040024e-2f; - NK_STORAGE const float a2 = -3.94382342128062756e-1f; - NK_STORAGE const float a3 = -1.18134036025221444e-1f; - NK_STORAGE const float a4 = +1.07123798512170878e-1f; - NK_STORAGE const float a5 = -1.86637164165180873e-2f; - NK_STORAGE const float a6 = +9.90140908664079833e-4f; - NK_STORAGE const float a7 = -5.23022132118824778e-14f; - return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7)))))); + /* New implementation. Also generated using lolremez. */ + /* Old version significantly deviated from expected results. */ + NK_STORAGE const float a0 = 9.9995999154986614e-1f; + NK_STORAGE const float a1 = 1.2548995793001028e-3f; + NK_STORAGE const float a2 = -5.0648546280678015e-1f; + NK_STORAGE const float a3 = 1.2942246466519995e-2f; + NK_STORAGE const float a4 = 2.8668384702547972e-2f; + NK_STORAGE const float a5 = 7.3726485210586547e-3f; + NK_STORAGE const float a6 = -3.8510875386947414e-3f; + NK_STORAGE const float a7 = 4.7196604604366623e-4f; + NK_STORAGE const float a8 = -1.8776444013090451e-5f; + return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*(a7 + x*a8))))))); } NK_LIB nk_uint nk_round_up_pow2(nk_uint v) @@ -7151,23 +7232,29 @@ nk_murmur_hash(const void * key, int len, nk_hash seed) { /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/ #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r))) - union {const nk_uint *i; const nk_byte *b;} conv = {0}; - const nk_byte *data = (const nk_byte*)key; - const int nblocks = len/4; + nk_uint h1 = seed; + nk_uint k1; + const nk_byte *data = (const nk_byte*)key; + const nk_byte *keyptr = data; + nk_byte *k1ptr; + const int bsize = sizeof(k1); + const int nblocks = len/4; + const nk_uint c1 = 0xcc9e2d51; const nk_uint c2 = 0x1b873593; const nk_byte *tail; - const nk_uint *blocks; - nk_uint k1; int i; /* body */ if (!key) return 0; - conv.b = (data + nblocks*4); - blocks = (const nk_uint*)conv.i; - for (i = -nblocks; i; ++i) { - k1 = blocks[i]; + for (i = 0; i < nblocks; ++i, keyptr += bsize) { + k1ptr = (nk_byte*)&k1; + k1ptr[0] = keyptr[0]; + k1ptr[1] = keyptr[1]; + k1ptr[2] = keyptr[2]; + k1ptr[3] = keyptr[3]; + k1 *= c1; k1 = NK_ROTL(k1,15); k1 *= c2; @@ -7181,15 +7268,15 @@ nk_murmur_hash(const void * key, int len, nk_hash seed) tail = (const nk_byte*)(data + nblocks*4); k1 = 0; switch (len & 3) { - case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */ - case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */ - case 1: k1 ^= tail[0]; + case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */ + case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */ + case 1: k1 ^= tail[0]; k1 *= c1; k1 = NK_ROTL(k1,15); k1 *= c2; h1 ^= k1; break; - default: break; + default: break; } /* finalization */ @@ -9356,7 +9443,7 @@ nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count) * backend (OpenGL, DirectX, ...). For example in OpenGL for `glDrawElements` * instead of specifing `GL_UNSIGNED_SHORT` you have to define `GL_UNSIGNED_INT`. * Sorry for the inconvenience. */ - NK_ASSERT((sizeof(nk_draw_index) == 2 && list->vertex_count < NK_USHORT_MAX && + if(sizeof(nk_draw_index)==2) NK_ASSERT((list->vertex_count < NK_USHORT_MAX && "To many verticies for 16-bit vertex indicies. Please read comment above on how to solve this problem")); return vtx; } @@ -12809,6 +12896,9 @@ nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int hei dst_font->ascent = ((float)unscaled_ascent * font_scale); dst_font->descent = ((float)unscaled_descent * font_scale); dst_font->glyph_offset = glyph_n; + // Need to zero this, or it will carry over from a previous + // bake, and cause a segfault when accessing glyphs[]. + dst_font->glyph_count = 0; } /* fill own baked font glyph array */ @@ -13903,8 +13993,12 @@ nk_input_key(struct nk_context *ctx, enum nk_keys key, int down) NK_ASSERT(ctx); if (!ctx) return; in = &ctx->input; +#ifdef NK_KEYSTATE_BASED_INPUT if (in->keyboard.keys[key].down != down) in->keyboard.keys[key].clicked++; +#else + in->keyboard.keys[key].clicked++; +#endif in->keyboard.keys[key].down = down; } NK_API void @@ -15788,7 +15882,7 @@ nk_panel_end(struct nk_context *ctx) nk_fill_rect(out, empty_space, 0, style->window.background); /* fill right empty space */ - empty_space.x = layout->bounds.x + layout->bounds.w - layout->border; + empty_space.x = layout->bounds.x + layout->bounds.w; empty_space.y = layout->bounds.y; empty_space.w = panel_padding.x + layout->border; empty_space.h = layout->bounds.h; @@ -15797,11 +15891,11 @@ nk_panel_end(struct nk_context *ctx) nk_fill_rect(out, empty_space, 0, style->window.background); /* fill bottom empty space */ - if (*layout->offset_x != 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) { + if (layout->footer_height > 0) { empty_space.x = window->bounds.x; empty_space.y = layout->bounds.y + layout->bounds.h; empty_space.w = window->bounds.w; - empty_space.h = scrollbar_size.y; + empty_space.h = layout->footer_height; nk_fill_rect(out, empty_space, 0, style->window.background); } } @@ -16175,8 +16269,8 @@ nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, { struct nk_window *win; struct nk_style *style; - nk_hash title_hash; - int title_len; + nk_hash name_hash; + int name_len; int ret = 0; NK_ASSERT(ctx); @@ -16189,12 +16283,12 @@ nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, /* find or create window */ style = &ctx->style; - title_len = (int)nk_strlen(name); - title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); - win = nk_find_window(ctx, title_hash, name); + name_len = (int)nk_strlen(name); + name_hash = nk_murmur_hash(name, (int)name_len, NK_WINDOW_TITLE); + win = nk_find_window(ctx, name_hash, name); if (!win) { /* create new window */ - nk_size name_length = (nk_size)nk_strlen(name); + nk_size name_length = (nk_size)name_len; win = (struct nk_window*)nk_create_window(ctx); NK_ASSERT(win); if (!win) return 0; @@ -16206,7 +16300,7 @@ nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, win->flags = flags; win->bounds = bounds; - win->name = title_hash; + win->name = name_hash; name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1); NK_MEMCPY(win->name_string, name, name_length); win->name_string[name_length] = 0; @@ -16434,6 +16528,20 @@ nk_window_get_panel(struct nk_context *ctx) if (!ctx || !ctx->current) return 0; return ctx->current->layout; } +NK_API void +nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y) +{ + struct nk_window *win; + NK_ASSERT(ctx); + NK_ASSERT(ctx->current); + if (!ctx || !ctx->current) + return ; + win = ctx->current; + if (offset_x) + *offset_x = win->scrollbar.x; + if (offset_y) + *offset_y = win->scrollbar.y; +} NK_API int nk_window_has_focus(const struct nk_context *ctx) { @@ -16600,6 +16708,18 @@ nk_window_set_size(struct nk_context *ctx, win->bounds.h = size.y; } NK_API void +nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y) +{ + struct nk_window *win; + NK_ASSERT(ctx); + NK_ASSERT(ctx->current); + if (!ctx || !ctx->current) + return; + win = ctx->current; + win->scrollbar.x = offset_x; + win->scrollbar.y = offset_y; +} +NK_API void nk_window_collapse(struct nk_context *ctx, const char *name, enum nk_collapse_states c) { @@ -16673,7 +16793,6 @@ nk_window_set_focus(struct nk_context *ctx, const char *name) - /* =============================================================== * * POPUP @@ -16807,7 +16926,11 @@ nk_nonblock_begin(struct nk_context *ctx, } else { /* close the popup if user pressed outside or in the header */ int pressed, in_body, in_header; +#ifdef NK_BUTTON_TRIGGER_ON_RELEASE + pressed = nk_input_is_mouse_released(&ctx->input, NK_BUTTON_LEFT); +#else pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT); +#endif in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body); in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header); if (pressed && (!in_body || in_header)) @@ -16898,7 +17021,38 @@ nk_popup_end(struct nk_context *ctx) ctx->current = win; nk_push_scissor(&win->buffer, win->layout->clip); } +NK_API void +nk_popup_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y) +{ + struct nk_window *popup; + NK_ASSERT(ctx); + NK_ASSERT(ctx->current); + NK_ASSERT(ctx->current->layout); + if (!ctx || !ctx->current || !ctx->current->layout) + return; + + popup = ctx->current; + if (offset_x) + *offset_x = popup->scrollbar.x; + if (offset_y) + *offset_y = popup->scrollbar.y; +} +NK_API void +nk_popup_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y) +{ + struct nk_window *popup; + + NK_ASSERT(ctx); + NK_ASSERT(ctx->current); + NK_ASSERT(ctx->current->layout); + if (!ctx || !ctx->current || !ctx->current->layout) + return; + + popup = ctx->current; + popup->scrollbar.x = offset_x; + popup->scrollbar.y = offset_y; +} @@ -18025,22 +18179,25 @@ nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type, layout->bounds.w, layout->row.columns); + #define NK_FRAC(x) (x - (int)x) /* will be used to remove fookin gaps */ /* calculate the width of one item inside the current layout space */ switch (layout->row.type) { case NK_LAYOUT_DYNAMIC_FIXED: { /* scaling fixed size widgets item width */ - item_width = NK_MAX(1.0f,panel_space) / (float)layout->row.columns; - item_offset = (float)layout->row.index * item_width; + float w = NK_MAX(1.0f,panel_space) / (float)layout->row.columns; + item_offset = (float)layout->row.index * w; + item_width = w + NK_FRAC(item_offset); item_spacing = (float)layout->row.index * spacing.x; } break; case NK_LAYOUT_DYNAMIC_ROW: { /* scaling single ratio widget width */ - item_width = layout->row.item_width * panel_space; + float w = layout->row.item_width * panel_space; item_offset = layout->row.item_offset; + item_width = w + NK_FRAC(item_offset); item_spacing = 0; if (modify) { - layout->row.item_offset += item_width + spacing.x; + layout->row.item_offset += w + spacing.x; layout->row.filled += layout->row.item_width; layout->row.index = 0; } @@ -18051,23 +18208,24 @@ nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, bounds->x -= (float)*layout->offset_x; bounds->y = layout->at_y + (layout->row.height * layout->row.item.y); bounds->y -= (float)*layout->offset_y; - bounds->w = layout->bounds.w * layout->row.item.w; - bounds->h = layout->row.height * layout->row.item.h; + bounds->w = layout->bounds.w * layout->row.item.w + NK_FRAC(bounds->x); + bounds->h = layout->row.height * layout->row.item.h + NK_FRAC(bounds->y); return; } case NK_LAYOUT_DYNAMIC: { /* scaling arrays of panel width ratios for every widget */ - float ratio; + float ratio, w; NK_ASSERT(layout->row.ratio); ratio = (layout->row.ratio[layout->row.index] < 0) ? layout->row.item_width : layout->row.ratio[layout->row.index]; + w = (ratio * panel_space); item_spacing = (float)layout->row.index * spacing.x; - item_width = (ratio * panel_space); item_offset = layout->row.item_offset; + item_width = w + NK_FRAC(item_offset); if (modify) { - layout->row.item_offset += item_width; + layout->row.item_offset += w; layout->row.filled += ratio; } } break; @@ -18105,13 +18263,16 @@ nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, } break; case NK_LAYOUT_TEMPLATE: { /* stretchy row layout with combined dynamic/static widget width*/ + float w; NK_ASSERT(layout->row.index < layout->row.columns); NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); - item_width = layout->row.templates[layout->row.index]; + w = layout->row.templates[layout->row.index]; item_offset = layout->row.item_offset; + item_width = w + NK_FRAC(item_offset); item_spacing = (float)layout->row.index * spacing.x; - if (modify) layout->row.item_offset += item_width; + if (modify) layout->row.item_offset += w; } break; + #undef NK_FRAC default: NK_ASSERT(0); break; }; @@ -18687,7 +18848,74 @@ nk_group_end(struct nk_context *ctx) { nk_group_scrolled_end(ctx); } +NK_API void +nk_group_get_scroll(struct nk_context *ctx, const char *id, nk_uint *x_offset, nk_uint *y_offset) +{ + int id_len; + nk_hash id_hash; + struct nk_window *win; + nk_uint *x_offset_ptr; + nk_uint *y_offset_ptr; + NK_ASSERT(ctx); + NK_ASSERT(id); + NK_ASSERT(ctx->current); + NK_ASSERT(ctx->current->layout); + if (!ctx || !ctx->current || !ctx->current->layout || !id) + return; + + /* find persistent group scrollbar value */ + win = ctx->current; + id_len = (int)nk_strlen(id); + id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP); + x_offset_ptr = nk_find_value(win, id_hash); + if (!x_offset_ptr) { + x_offset_ptr = nk_add_value(ctx, win, id_hash, 0); + y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0); + + NK_ASSERT(x_offset_ptr); + NK_ASSERT(y_offset_ptr); + if (!x_offset_ptr || !y_offset_ptr) return; + *x_offset_ptr = *y_offset_ptr = 0; + } else y_offset_ptr = nk_find_value(win, id_hash+1); + if (x_offset) + *x_offset = *x_offset_ptr; + if (y_offset) + *y_offset = *y_offset_ptr; +} +NK_API void +nk_group_set_scroll(struct nk_context *ctx, const char *id, nk_uint x_offset, nk_uint y_offset) +{ + int id_len; + nk_hash id_hash; + struct nk_window *win; + nk_uint *x_offset_ptr; + nk_uint *y_offset_ptr; + + NK_ASSERT(ctx); + NK_ASSERT(id); + NK_ASSERT(ctx->current); + NK_ASSERT(ctx->current->layout); + if (!ctx || !ctx->current || !ctx->current->layout || !id) + return; + + /* find persistent group scrollbar value */ + win = ctx->current; + id_len = (int)nk_strlen(id); + id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP); + x_offset_ptr = nk_find_value(win, id_hash); + if (!x_offset_ptr) { + x_offset_ptr = nk_add_value(ctx, win, id_hash, 0); + y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0); + + NK_ASSERT(x_offset_ptr); + NK_ASSERT(y_offset_ptr); + if (!x_offset_ptr || !y_offset_ptr) return; + *x_offset_ptr = *y_offset_ptr = 0; + } else y_offset_ptr = nk_find_value(win, id_hash+1); + *x_offset_ptr = x_offset; + *y_offset_ptr = y_offset; +} @@ -21179,6 +21407,7 @@ nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, { nk_flags ws = 0; int left_mouse_down; + int left_mouse_clicked; int left_mouse_click_in_cursor; float scroll_delta; @@ -21186,13 +21415,14 @@ nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, if (!in) return scroll_offset; left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; + left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked; left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, *cursor, nk_true); if (nk_input_is_mouse_hovering_rect(in, *scroll)) *state = NK_WIDGET_STATE_HOVERED; scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x; - if (left_mouse_down && left_mouse_click_in_cursor) { + if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) { /* update cursor by mouse dragging */ float pixel, delta; *state = NK_WIDGET_STATE_ACTIVE; @@ -25243,172 +25473,182 @@ nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args) /// - [yy]: Minor version with non-breaking API and library changes /// - [zz]: Bug fix version with no direct changes to API /// -/// - 2018/04/01 (4.00.1) - Fixed calling `nk_convert` multiple time per single frame +/// - 2019/09/20 (4.01.3) - Fixed a bug wherein combobox cannot be closed by clicking the header +/// when NK_BUTTON_TRIGGER_ON_RELEASE is defined. +/// - 2019/09/10 (4.01.2) - Fixed the nk_cos function, which deviated significantly. +/// - 2019/09/08 (4.01.1) - Fixed a bug wherein re-baking of fonts caused a segmentation +/// fault due to dst_font->glyph_count not being zeroed on subsequent +/// bakes of the same set of fonts. +/// - 2019/06/23 (4.01.0) - Added nk_***_get_scroll and nk_***_set_scroll for groups, windows, and popups. +/// - 2019/06/12 (4.00.3) - Fix panel background drawing bug. +/// - 2018/10/31 (4.00.2) - Added NK_KEYSTATE_BASED_INPUT to "fix" state based backends +/// like GLFW without breaking key repeat behavior on event based. +/// - 2018/04/01 (4.00.1) - Fixed calling `nk_convert` multiple time per single frame. /// - 2018/04/01 (4.00.0) - BREAKING CHANGE: nk_draw_list_clear no longer tries to -/// clear provided buffers. So make sure to either free -/// or clear each passed buffer after calling nk_convert. -/// - 2018/02/23 (3.00.6) - Fixed slider dragging behavior -/// - 2018/01/31 (3.00.5) - Fixed overcalculation of cursor data in font baking process -/// - 2018/01/31 (3.00.4) - Removed name collision with stb_truetype -/// - 2018/01/28 (3.00.3) - Fixed panel window border drawing bug -/// - 2018/01/12 (3.00.2) - Added `nk_group_begin_titled` for separed group identifier and title -/// - 2018/01/07 (3.00.1) - Started to change documentation style +/// clear provided buffers. So make sure to either free +/// or clear each passed buffer after calling nk_convert. +/// - 2018/02/23 (3.00.6) - Fixed slider dragging behavior. +/// - 2018/01/31 (3.00.5) - Fixed overcalculation of cursor data in font baking process. +/// - 2018/01/31 (3.00.4) - Removed name collision with stb_truetype. +/// - 2018/01/28 (3.00.3) - Fixed panel window border drawing bug. +/// - 2018/01/12 (3.00.2) - Added `nk_group_begin_titled` for separed group identifier and title. +/// - 2018/01/07 (3.00.1) - Started to change documentation style. /// - 2018/01/05 (3.00.0) - BREAKING CHANGE: The previous color picker API was broken /// because of conversions between float and byte color representation. /// Color pickers now use floating point values to represent /// HSV values. To get back the old behavior I added some additional /// color conversion functions to cast between nk_color and /// nk_colorf. -/// - 2017/12/23 (2.00.7) - Fixed small warning -/// - 2017/12/23 (2.00.7) - Fixed nk_edit_buffer behavior if activated to allow input -/// - 2017/12/23 (2.00.7) - Fixed modifyable progressbar dragging visuals and input behavior -/// - 2017/12/04 (2.00.6) - Added formated string tooltip widget -/// - 2017/11/18 (2.00.5) - Fixed window becoming hidden with flag NK_WINDOW_NO_INPUT -/// - 2017/11/15 (2.00.4) - Fixed font merging -/// - 2017/11/07 (2.00.3) - Fixed window size and position modifier functions -/// - 2017/09/14 (2.00.2) - Fixed nk_edit_buffer and nk_edit_focus behavior -/// - 2017/09/14 (2.00.1) - Fixed window closing behavior +/// - 2017/12/23 (2.00.7) - Fixed small warning. +/// - 2017/12/23 (2.00.7) - Fixed `nk_edit_buffer` behavior if activated to allow input. +/// - 2017/12/23 (2.00.7) - Fixed modifyable progressbar dragging visuals and input behavior. +/// - 2017/12/04 (2.00.6) - Added formated string tooltip widget. +/// - 2017/11/18 (2.00.5) - Fixed window becoming hidden with flag `NK_WINDOW_NO_INPUT`. +/// - 2017/11/15 (2.00.4) - Fixed font merging. +/// - 2017/11/07 (2.00.3) - Fixed window size and position modifier functions. +/// - 2017/09/14 (2.00.2) - Fixed `nk_edit_buffer` and `nk_edit_focus` behavior. +/// - 2017/09/14 (2.00.1) - Fixed window closing behavior. /// - 2017/09/14 (2.00.0) - BREAKING CHANGE: Modifing window position and size funtions now /// require the name of the window and must happen outside the window /// building process (between function call nk_begin and nk_end). -/// - 2017/09/11 (1.40.9) - Fixed window background flag if background window is declared last -/// - 2017/08/27 (1.40.8) - Fixed `nk_item_is_any_active` for hidden windows -/// - 2017/08/27 (1.40.7) - Fixed window background flag +/// - 2017/09/11 (1.40.9) - Fixed window background flag if background window is declared last. +/// - 2017/08/27 (1.40.8) - Fixed `nk_item_is_any_active` for hidden windows. +/// - 2017/08/27 (1.40.7) - Fixed window background flag. /// - 2017/07/07 (1.40.6) - Fixed missing clipping rect check for hovering/clicked -/// query for widgets +/// query for widgets. /// - 2017/07/07 (1.40.5) - Fixed drawing bug for vertex output for lines and stroked -/// and filled rectangles +/// and filled rectangles. /// - 2017/07/07 (1.40.4) - Fixed bug in nk_convert trying to add windows that are in /// process of being destroyed. /// - 2017/07/07 (1.40.3) - Fixed table internal bug caused by storing table size in /// window instead of directly in table. -/// - 2017/06/30 (1.40.2) - Removed unneeded semicolon in C++ NK_ALIGNOF macro -/// - 2017/06/30 (1.40.1) - Fixed drawing lines smaller or equal zero +/// - 2017/06/30 (1.40.2) - Removed unneeded semicolon in C++ NK_ALIGNOF macro. +/// - 2017/06/30 (1.40.1) - Fixed drawing lines smaller or equal zero. /// - 2017/06/08 (1.40.0) - Removed the breaking part of last commit. Auto layout now only -/// comes in effect if you pass in zero was row height argument +/// comes in effect if you pass in zero was row height argument. /// - 2017/06/08 (1.40.0) - BREAKING CHANGE: while not directly API breaking it will change /// how layouting works. From now there will be an internal minimum /// row height derived from font height. If you need a row smaller than /// that you can directly set it by `nk_layout_set_min_row_height` and /// reset the value back by calling `nk_layout_reset_min_row_height. -/// - 2017/06/08 (1.39.1) - Fixed property text edit handling bug caused by past `nk_widget` fix -/// - 2017/06/08 (1.39.0) - Added function to retrieve window space without calling a nk_layout_xxx function -/// - 2017/06/06 (1.38.5) - Fixed `nk_convert` return flag for command buffer -/// - 2017/05/23 (1.38.4) - Fixed activation behavior for widgets partially clipped -/// - 2017/05/10 (1.38.3) - Fixed wrong min window size mouse scaling over boundries -/// - 2017/05/09 (1.38.2) - Fixed vertical scrollbar drawing with not enough space -/// - 2017/05/09 (1.38.1) - Fixed scaler dragging behavior if window size hits minimum size -/// - 2017/05/06 (1.38.0) - Added platform double-click support -/// - 2017/04/20 (1.37.1) - Fixed key repeat found inside glfw demo backends -/// - 2017/04/20 (1.37.0) - Extended properties with selection and clipbard support -/// - 2017/04/20 (1.36.2) - Fixed #405 overlapping rows with zero padding and spacing -/// - 2017/04/09 (1.36.1) - Fixed #403 with another widget float error -/// - 2017/04/09 (1.36.0) - Added window `NK_WINDOW_NO_INPUT` and `NK_WINDOW_NOT_INTERACTIVE` flags -/// - 2017/04/09 (1.35.3) - Fixed buffer heap corruption -/// - 2017/03/25 (1.35.2) - Fixed popup overlapping for `NK_WINDOW_BACKGROUND` windows -/// - 2017/03/25 (1.35.1) - Fixed windows closing behavior -/// - 2017/03/18 (1.35.0) - Added horizontal scroll requested in #377 -/// - 2017/03/18 (1.34.3) - Fixed long window header titles -/// - 2017/03/04 (1.34.2) - Fixed text edit filtering -/// - 2017/03/04 (1.34.1) - Fixed group closable flag -/// - 2017/02/25 (1.34.0) - Added custom draw command for better language binding support -/// - 2017/01/24 (1.33.0) - Added programatic way of remove edit focus -/// - 2017/01/24 (1.32.3) - Fixed wrong define for basic type definitions for windows -/// - 2017/01/21 (1.32.2) - Fixed input capture from hidden or closed windows -/// - 2017/01/21 (1.32.1) - Fixed slider behavior and drawing -/// - 2017/01/13 (1.32.0) - Added flag to put scaler into the bottom left corner +/// - 2017/06/08 (1.39.1) - Fixed property text edit handling bug caused by past `nk_widget` fix. +/// - 2017/06/08 (1.39.0) - Added function to retrieve window space without calling a `nk_layout_xxx` function. +/// - 2017/06/06 (1.38.5) - Fixed `nk_convert` return flag for command buffer. +/// - 2017/05/23 (1.38.4) - Fixed activation behavior for widgets partially clipped. +/// - 2017/05/10 (1.38.3) - Fixed wrong min window size mouse scaling over boundries. +/// - 2017/05/09 (1.38.2) - Fixed vertical scrollbar drawing with not enough space. +/// - 2017/05/09 (1.38.1) - Fixed scaler dragging behavior if window size hits minimum size. +/// - 2017/05/06 (1.38.0) - Added platform double-click support. +/// - 2017/04/20 (1.37.1) - Fixed key repeat found inside glfw demo backends. +/// - 2017/04/20 (1.37.0) - Extended properties with selection and clipboard support. +/// - 2017/04/20 (1.36.2) - Fixed #405 overlapping rows with zero padding and spacing. +/// - 2017/04/09 (1.36.1) - Fixed #403 with another widget float error. +/// - 2017/04/09 (1.36.0) - Added window `NK_WINDOW_NO_INPUT` and `NK_WINDOW_NOT_INTERACTIVE` flags. +/// - 2017/04/09 (1.35.3) - Fixed buffer heap corruption. +/// - 2017/03/25 (1.35.2) - Fixed popup overlapping for `NK_WINDOW_BACKGROUND` windows. +/// - 2017/03/25 (1.35.1) - Fixed windows closing behavior. +/// - 2017/03/18 (1.35.0) - Added horizontal scroll requested in #377. +/// - 2017/03/18 (1.34.3) - Fixed long window header titles. +/// - 2017/03/04 (1.34.2) - Fixed text edit filtering. +/// - 2017/03/04 (1.34.1) - Fixed group closable flag. +/// - 2017/02/25 (1.34.0) - Added custom draw command for better language binding support. +/// - 2017/01/24 (1.33.0) - Added programatic way of remove edit focus. +/// - 2017/01/24 (1.32.3) - Fixed wrong define for basic type definitions for windows. +/// - 2017/01/21 (1.32.2) - Fixed input capture from hidden or closed windows. +/// - 2017/01/21 (1.32.1) - Fixed slider behavior and drawing. +/// - 2017/01/13 (1.32.0) - Added flag to put scaler into the bottom left corner. /// - 2017/01/13 (1.31.0) - Added additional row layouting method to combine both /// dynamic and static widgets. -/// - 2016/12/31 (1.30.0) - Extended scrollbar offset from 16-bit to 32-bit -/// - 2016/12/31 (1.29.2)- Fixed closing window bug of minimized windows -/// - 2016/12/03 (1.29.1)- Fixed wrapped text with no seperator and C89 error -/// - 2016/12/03 (1.29.0) - Changed text wrapping to process words not characters -/// - 2016/11/22 (1.28.6)- Fixed window minimized closing bug -/// - 2016/11/19 (1.28.5)- Fixed abstract combo box closing behavior -/// - 2016/11/19 (1.28.4)- Fixed tooltip flickering -/// - 2016/11/19 (1.28.3)- Fixed memory leak caused by popup repeated closing -/// - 2016/11/18 (1.28.2)- Fixed memory leak caused by popup panel allocation -/// - 2016/11/10 (1.28.1)- Fixed some warnings and C++ error -/// - 2016/11/10 (1.28.0)- Added additional `nk_button` versions which allows to directly +/// - 2016/12/31 (1.30.0) - Extended scrollbar offset from 16-bit to 32-bit. +/// - 2016/12/31 (1.29.2) - Fixed closing window bug of minimized windows. +/// - 2016/12/03 (1.29.1) - Fixed wrapped text with no seperator and C89 error. +/// - 2016/12/03 (1.29.0) - Changed text wrapping to process words not characters. +/// - 2016/11/22 (1.28.6) - Fixed window minimized closing bug. +/// - 2016/11/19 (1.28.5) - Fixed abstract combo box closing behavior. +/// - 2016/11/19 (1.28.4) - Fixed tooltip flickering. +/// - 2016/11/19 (1.28.3) - Fixed memory leak caused by popup repeated closing. +/// - 2016/11/18 (1.28.2) - Fixed memory leak caused by popup panel allocation. +/// - 2016/11/10 (1.28.1) - Fixed some warnings and C++ error. +/// - 2016/11/10 (1.28.0) - Added additional `nk_button` versions which allows to directly /// pass in a style struct to change buttons visual. -/// - 2016/11/10 (1.27.0)- Added additional 'nk_tree' versions to support external state +/// - 2016/11/10 (1.27.0) - Added additional `nk_tree` versions to support external state /// storage. Just like last the `nk_group` commit the main /// advantage is that you optionally can minimize nuklears runtime /// memory consumption or handle hash collisions. -/// - 2016/11/09 (1.26.0)- Added additional `nk_group` version to support external scrollbar +/// - 2016/11/09 (1.26.0) - Added additional `nk_group` version to support external scrollbar /// offset storage. Main advantage is that you can externalize /// the memory management for the offset. It could also be helpful /// if you have a hash collision in `nk_group_begin` but really /// want the name. In addition I added `nk_list_view` which allows /// to draw big lists inside a group without actually having to /// commit the whole list to nuklear (issue #269). -/// - 2016/10/30 (1.25.1)- Fixed clipping rectangle bug inside `nk_draw_list` -/// - 2016/10/29 (1.25.0)- Pulled `nk_panel` memory management into nuklear and out of +/// - 2016/10/30 (1.25.1) - Fixed clipping rectangle bug inside `nk_draw_list`. +/// - 2016/10/29 (1.25.0) - Pulled `nk_panel` memory management into nuklear and out of /// the hands of the user. From now on users don't have to care /// about panels unless they care about some information. If you /// still need the panel just call `nk_window_get_panel`. -/// - 2016/10/21 (1.24.0)- Changed widget border drawing to stroked rectangle from filled +/// - 2016/10/21 (1.24.0) - Changed widget border drawing to stroked rectangle from filled /// rectangle for less overdraw and widget background transparency. -/// - 2016/10/18 (1.23.0)- Added `nk_edit_focus` for manually edit widget focus control -/// - 2016/09/29 (1.22.7)- Fixed deduction of basic type in non `` compilation -/// - 2016/09/29 (1.22.6)- Fixed edit widget UTF-8 text cursor drawing bug -/// - 2016/09/28 (1.22.5)- Fixed edit widget UTF-8 text appending/inserting/removing -/// - 2016/09/28 (1.22.4)- Fixed drawing bug inside edit widgets which offset all text +/// - 2016/10/18 (1.23.0) - Added `nk_edit_focus` for manually edit widget focus control. +/// - 2016/09/29 (1.22.7) - Fixed deduction of basic type in non `` compilation. +/// - 2016/09/29 (1.22.6) - Fixed edit widget UTF-8 text cursor drawing bug. +/// - 2016/09/28 (1.22.5) - Fixed edit widget UTF-8 text appending/inserting/removing. +/// - 2016/09/28 (1.22.4) - Fixed drawing bug inside edit widgets which offset all text /// text in every edit widget if one of them is scrolled. -/// - 2016/09/28 (1.22.3)- Fixed small bug in edit widgets if not active. The wrong +/// - 2016/09/28 (1.22.3) - Fixed small bug in edit widgets if not active. The wrong /// text length is passed. It should have been in bytes but /// was passed as glyphes. -/// - 2016/09/20 (1.22.2)- Fixed color button size calculation -/// - 2016/09/20 (1.22.1)- Fixed some `nk_vsnprintf` behavior bugs and removed -/// `` again from `NK_INCLUDE_STANDARD_VARARGS`. -/// - 2016/09/18 (1.22.0)- C89 does not support vsnprintf only C99 and newer as well +/// - 2016/09/20 (1.22.2) - Fixed color button size calculation. +/// - 2016/09/20 (1.22.1) - Fixed some `nk_vsnprintf` behavior bugs and removed `` +/// again from `NK_INCLUDE_STANDARD_VARARGS`. +/// - 2016/09/18 (1.22.0) - C89 does not support vsnprintf only C99 and newer as well /// as C++11 and newer. In addition to use vsnprintf you have /// to include . So just defining `NK_INCLUDE_STD_VAR_ARGS` /// is not enough. That behavior is now fixed. By default if /// both varargs as well as stdio is selected I try to use /// vsnprintf if not possible I will revert to vsprintf. If /// varargs but not stdio was defined I will use my own function. -/// - 2016/09/15 (1.21.2)- Fixed panel `close` behavior for deeper panel levels -/// - 2016/09/15 (1.21.1)- Fixed C++ errors and wrong argument to `nk_panel_get_xxxx` +/// - 2016/09/15 (1.21.2) - Fixed panel `close` behavior for deeper panel levels. +/// - 2016/09/15 (1.21.1) - Fixed C++ errors and wrong argument to `nk_panel_get_xxxx`. /// - 2016/09/13 (1.21.0) - !BREAKING! Fixed nonblocking popup behavior in menu, combo, /// and contextual which prevented closing in y-direction if /// popup did not reach max height. /// In addition the height parameter was changed into vec2 /// for width and height to have more control over the popup size. -/// - 2016/09/13 (1.20.3) - Cleaned up and extended type selection -/// - 2016/09/13 (1.20.2)- Fixed slider behavior hopefully for the last time. This time +/// - 2016/09/13 (1.20.3) - Cleaned up and extended type selection. +/// - 2016/09/13 (1.20.2) - Fixed slider behavior hopefully for the last time. This time /// all calculation are correct so no more hackery. -/// - 2016/09/13 (1.20.1)- Internal change to divide window/panel flags into panel flags and types. +/// - 2016/09/13 (1.20.1) - Internal change to divide window/panel flags into panel flags and types. /// Suprisinly spend years in C and still happened to confuse types /// with flags. Probably something to take note. -/// - 2016/09/08 (1.20.0)- Added additional helper function to make it easier to just +/// - 2016/09/08 (1.20.0) - Added additional helper function to make it easier to just /// take the produced buffers from `nk_convert` and unplug the /// iteration process from `nk_context`. So now you can /// just use the vertex,element and command buffer + two pointer /// inside the command buffer retrieved by calls `nk__draw_begin` /// and `nk__draw_end` and macro `nk_draw_foreach_bounded`. -/// - 2016/09/08 (1.19.0)- Added additional asserts to make sure every `nk_xxx_begin` call +/// - 2016/09/08 (1.19.0) - Added additional asserts to make sure every `nk_xxx_begin` call /// for windows, popups, combobox, menu and contextual is guarded by /// `if` condition and does not produce false drawing output. -/// - 2016/09/08 (1.18.0)- Changed confusing name for `NK_SYMBOL_RECT_FILLED`, `NK_SYMBOL_RECT` +/// - 2016/09/08 (1.18.0) - Changed confusing name for `NK_SYMBOL_RECT_FILLED`, `NK_SYMBOL_RECT` /// to hopefully easier to understand `NK_SYMBOL_RECT_FILLED` and /// `NK_SYMBOL_RECT_OUTLINE`. -/// - 2016/09/08 (1.17.0)- Changed confusing name for `NK_SYMBOL_CIRLCE_FILLED`, `NK_SYMBOL_CIRCLE` +/// - 2016/09/08 (1.17.0) - Changed confusing name for `NK_SYMBOL_CIRLCE_FILLED`, `NK_SYMBOL_CIRCLE` /// to hopefully easier to understand `NK_SYMBOL_CIRCLE_FILLED` and /// `NK_SYMBOL_CIRCLE_OUTLINE`. -/// - 2016/09/08 (1.16.0)- Added additional checks to select correct types if `NK_INCLUDE_FIXED_TYPES` +/// - 2016/09/08 (1.16.0) - Added additional checks to select correct types if `NK_INCLUDE_FIXED_TYPES` /// is not defined by supporting the biggest compiler GCC, clang and MSVC. -/// - 2016/09/07 (1.15.3)- Fixed `NK_INCLUDE_COMMAND_USERDATA` define to not cause an error -/// - 2016/09/04 (1.15.2)- Fixed wrong combobox height calculation -/// - 2016/09/03 (1.15.1)- Fixed gaps inside combo boxes in OpenGL +/// - 2016/09/07 (1.15.3) - Fixed `NK_INCLUDE_COMMAND_USERDATA` define to not cause an error. +/// - 2016/09/04 (1.15.2) - Fixed wrong combobox height calculation. +/// - 2016/09/03 (1.15.1) - Fixed gaps inside combo boxes in OpenGL. /// - 2016/09/02 (1.15.0) - Changed nuklear to not have any default vertex layout and /// instead made it user provided. The range of types to convert /// to is quite limited at the moment, but I would be more than /// happy to accept PRs to add additional. -/// - 2016/08/30 (1.14.2) - Removed unused variables -/// - 2016/08/30 (1.14.1) - Fixed C++ build errors -/// - 2016/08/30 (1.14.0) - Removed mouse dragging from SDL demo since it does not work correctly -/// - 2016/08/30 (1.13.4) - Tweaked some default styling variables +/// - 2016/08/30 (1.14.2) - Removed unused variables. +/// - 2016/08/30 (1.14.1) - Fixed C++ build errors. +/// - 2016/08/30 (1.14.0) - Removed mouse dragging from SDL demo since it does not work correctly. +/// - 2016/08/30 (1.13.4) - Tweaked some default styling variables. /// - 2016/08/30 (1.13.3) - Hopefully fixed drawing bug in slider, in general I would /// refrain from using slider with a big number of steps. /// - 2016/08/30 (1.13.2) - Fixed close and minimize button which would fire even if the @@ -25418,36 +25658,36 @@ nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args) /// - 2016/08/30 (1.13.0) - Removed `NK_WINDOW_DYNAMIC` flag from public API since /// it is bugged and causes issues in window selection. /// - 2016/08/30 (1.12.0) - Removed scaler size. The size of the scaler is now -/// determined by the scrollbar size -/// - 2016/08/30 (1.11.2) - Fixed some drawing bugs caused by changes from 1.11 -/// - 2016/08/30 (1.11.1) - Fixed overlapping minimized window selection +/// determined by the scrollbar size. +/// - 2016/08/30 (1.11.2) - Fixed some drawing bugs caused by changes from 1.11.0. +/// - 2016/08/30 (1.11.1) - Fixed overlapping minimized window selection. /// - 2016/08/30 (1.11.0) - Removed some internal complexity and overly complex code /// handling panel padding and panel border. -/// - 2016/08/29 (1.10.0) - Added additional height parameter to `nk_combobox_xxx` -/// - 2016/08/29 (1.10.0) - Fixed drawing bug in dynamic popups -/// - 2016/08/29 (1.10.0) - Added experimental mouse scrolling to popups, menus and comboboxes +/// - 2016/08/29 (1.10.0) - Added additional height parameter to `nk_combobox_xxx`. +/// - 2016/08/29 (1.10.0) - Fixed drawing bug in dynamic popups. +/// - 2016/08/29 (1.10.0) - Added experimental mouse scrolling to popups, menus and comboboxes. /// - 2016/08/26 (1.10.0) - Added window name string prepresentation to account for -/// hash collisions. Currently limited to NK_WINDOW_MAX_NAME +/// hash collisions. Currently limited to `NK_WINDOW_MAX_NAME` /// which in term can be redefined if not big enough. -/// - 2016/08/26 (1.10.0) - Added stacks for temporary style/UI changes in code +/// - 2016/08/26 (1.10.0) - Added stacks for temporary style/UI changes in code. /// - 2016/08/25 (1.10.0) - Changed `nk_input_is_key_pressed` and 'nk_input_is_key_released' /// to account for key press and release happening in one frame. -/// - 2016/08/25 (1.10.0) - Added additional nk_edit flag to directly jump to the end on activate -/// - 2016/08/17 (1.09.6)- Removed invalid check for value zero in nk_propertyx -/// - 2016/08/16 (1.09.5)- Fixed ROM mode for deeper levels of popup windows parents. -/// - 2016/08/15 (1.09.4)- Editbox are now still active if enter was pressed with flag +/// - 2016/08/25 (1.10.0) - Added additional nk_edit flag to directly jump to the end on activate. +/// - 2016/08/17 (1.09.6) - Removed invalid check for value zero in `nk_propertyx`. +/// - 2016/08/16 (1.09.5) - Fixed ROM mode for deeper levels of popup windows parents. +/// - 2016/08/15 (1.09.4) - Editbox are now still active if enter was pressed with flag /// `NK_EDIT_SIG_ENTER`. Main reasoning is to be able to keep /// typing after commiting. -/// - 2016/08/15 (1.09.4)- Removed redundant code -/// - 2016/08/15 (1.09.4)- Fixed negative numbers in `nk_strtoi` and remove unused variable -/// - 2016/08/15 (1.09.3)- Fixed `NK_WINDOW_BACKGROUND` flag behavior to select a background +/// - 2016/08/15 (1.09.4) - Removed redundant code. +/// - 2016/08/15 (1.09.4) - Fixed negative numbers in `nk_strtoi` and remove unused variable. +/// - 2016/08/15 (1.09.3) - Fixed `NK_WINDOW_BACKGROUND` flag behavior to select a background /// window only as selected by hovering and not by clicking. -/// - 2016/08/14 (1.09.2)- Fixed a bug in font atlas which caused wrong loading +/// - 2016/08/14 (1.09.2) - Fixed a bug in font atlas which caused wrong loading /// of glyphes for font with multiple ranges. -/// - 2016/08/12 (1.09.1)- Added additional function to check if window is currently +/// - 2016/08/12 (1.09.1) - Added additional function to check if window is currently /// hidden and therefore not visible. -/// - 2016/08/12 (1.09.1)- nk_window_is_closed now queries the correct flag `NK_WINDOW_CLOSED` -/// instead of the old flag `NK_WINDOW_HIDDEN` +/// - 2016/08/12 (1.09.1) - nk_window_is_closed now queries the correct flag `NK_WINDOW_CLOSED` +/// instead of the old flag `NK_WINDOW_HIDDEN`. /// - 2016/08/09 (1.09.0) - Added additional double version to nk_property and changed /// the underlying implementation to not cast to float and instead /// work directly on the given values. @@ -25457,8 +25697,8 @@ nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args) /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal /// string to floating point number conversion for additional /// precision. -/// - 2016/08/08 (1.07.2)- Fixed compiling error without define NK_INCLUDE_FIXED_TYPE -/// - 2016/08/08 (1.07.1)- Fixed possible floating point error inside `nk_widget` leading +/// - 2016/08/08 (1.07.2) - Fixed compiling error without define `NK_INCLUDE_FIXED_TYPE`. +/// - 2016/08/08 (1.07.1) - Fixed possible floating point error inside `nk_widget` leading /// to wrong wiget width calculation which results in widgets falsly /// becomming tagged as not inside window and cannot be accessed. /// - 2016/08/08 (1.07.0) - Nuklear now differentiates between hiding a window (NK_WINDOW_HIDDEN) and @@ -25469,31 +25709,31 @@ nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args) /// remain. /// - 2016/08/08 (1.06.0) - Added `nk_edit_string_zero_terminated` as a second option to /// `nk_edit_string` which takes, edits and outputs a '\0' terminated string. -/// - 2016/08/08 (1.05.4)- Fixed scrollbar auto hiding behavior -/// - 2016/08/08 (1.05.3)- Fixed wrong panel padding selection in `nk_layout_widget_space` -/// - 2016/08/07 (1.05.2)- Fixed old bug in dynamic immediate mode layout API, calculating +/// - 2016/08/08 (1.05.4) - Fixed scrollbar auto hiding behavior. +/// - 2016/08/08 (1.05.3) - Fixed wrong panel padding selection in `nk_layout_widget_space`. +/// - 2016/08/07 (1.05.2) - Fixed old bug in dynamic immediate mode layout API, calculating /// wrong item spacing and panel width. -///- 2016/08/07 (1.05.1)- Hopefully finally fixed combobox popup drawing bug -///- 2016/08/07 (1.05.0) - Split varargs away from NK_INCLUDE_STANDARD_IO into own -/// define NK_INCLUDE_STANDARD_VARARGS to allow more fine +/// - 2016/08/07 (1.05.1) - Hopefully finally fixed combobox popup drawing bug. +/// - 2016/08/07 (1.05.0) - Split varargs away from `NK_INCLUDE_STANDARD_IO` into own +/// define `NK_INCLUDE_STANDARD_VARARGS` to allow more fine /// grained controlled over library includes. -/// - 2016/08/06 (1.04.5)- Changed memset calls to NK_MEMSET -/// - 2016/08/04 (1.04.4)- Fixed fast window scaling behavior -/// - 2016/08/04 (1.04.3)- Fixed window scaling, movement bug which appears if you +/// - 2016/08/06 (1.04.5) - Changed memset calls to `NK_MEMSET`. +/// - 2016/08/04 (1.04.4) - Fixed fast window scaling behavior. +/// - 2016/08/04 (1.04.3) - Fixed window scaling, movement bug which appears if you /// move/scale a window and another window is behind it. /// If you are fast enough then the window behind gets activated /// and the operation is blocked. I now require activating /// by hovering only if mouse is not pressed. -/// - 2016/08/04 (1.04.2)- Fixed changing fonts -/// - 2016/08/03 (1.04.1)- Fixed `NK_WINDOW_BACKGROUND` behavior -/// - 2016/08/03 (1.04.0) - Added color parameter to `nk_draw_image` +/// - 2016/08/04 (1.04.2) - Fixed changing fonts. +/// - 2016/08/03 (1.04.1) - Fixed `NK_WINDOW_BACKGROUND` behavior. +/// - 2016/08/03 (1.04.0) - Added color parameter to `nk_draw_image`. /// - 2016/08/03 (1.04.0) - Added additional window padding style attributes for -/// sub windows (combo, menu, ...) -/// - 2016/08/03 (1.04.0) - Added functions to show/hide software cursor +/// sub windows (combo, menu, ...). +/// - 2016/08/03 (1.04.0) - Added functions to show/hide software cursor. /// - 2016/08/03 (1.04.0) - Added `NK_WINDOW_BACKGROUND` flag to force a window -/// to be always in the background of the screen -/// - 2016/08/03 (1.03.2)- Removed invalid assert macro for NK_RGB color picker -/// - 2016/08/01 (1.03.1)- Added helper macros into header include guard +/// to be always in the background of the screen. +/// - 2016/08/03 (1.03.2) - Removed invalid assert macro for NK_RGB color picker. +/// - 2016/08/01 (1.03.1) - Added helper macros into header include guard. /// - 2016/07/29 (1.03.0) - Moved the window/table pool into the header part to /// simplify memory management by removing the need to /// allocate the pool. @@ -25501,16 +25741,15 @@ nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args) /// will hide the window scrollbar after NK_SCROLLBAR_HIDING_TIMEOUT /// seconds without window interaction. To make it work /// you have to also set a delta time inside the `nk_context`. -/// - 2016/07/25 (1.01.1) - Fixed small panel and panel border drawing bugs -/// - 2016/07/15 (1.01.0) - Added software cursor to `nk_style` and `nk_context` -/// - 2016/07/15 (1.01.0) - Added const correctness to `nk_buffer_push' data argument +/// - 2016/07/25 (1.01.1) - Fixed small panel and panel border drawing bugs. +/// - 2016/07/15 (1.01.0) - Added software cursor to `nk_style` and `nk_context`. +/// - 2016/07/15 (1.01.0) - Added const correctness to `nk_buffer_push' data argument. /// - 2016/07/15 (1.01.0) - Removed internal font baking API and simplified /// font atlas memory management by converting pointer /// arrays for fonts and font configurations to lists. /// - 2016/07/15 (1.00.0) - Changed button API to use context dependend button /// behavior instead of passing it for every function call. /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - /// ## Gallery /// ![Figure [blue]: Feature overview with blue color styling](https://cloud.githubusercontent.com/assets/8057201/13538240/acd96876-e249-11e5-9547-5ac0b19667a0.png) /// ![Figure [red]: Feature overview with red color styling](https://cloud.githubusercontent.com/assets/8057201/13538243/b04acd4c-e249-11e5-8fd2-ad7744a5b446.png) diff --git a/deps/nuklear_glfw_gl2.h b/deps/nuklear_glfw_gl2.h index 61acc29c..a959b14a 100644 --- a/deps/nuklear_glfw_gl2.h +++ b/deps/nuklear_glfw_gl2.h @@ -230,7 +230,7 @@ nk_glfw3_mouse_button_callback(GLFWwindow* window, int button, int action, int m } NK_INTERN void -nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit) +nk_glfw3_clipboard_paste(nk_handle usr, struct nk_text_edit *edit) { const char *text = glfwGetClipboardString(glfw.win); if (text) nk_textedit_paste(edit, text, nk_strlen(text)); @@ -238,7 +238,7 @@ nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit) } NK_INTERN void -nk_glfw3_clipbard_copy(nk_handle usr, const char *text, int len) +nk_glfw3_clipboard_copy(nk_handle usr, const char *text, int len) { char *str = 0; (void)usr; @@ -261,8 +261,8 @@ nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state) glfwSetMouseButtonCallback(win, nk_glfw3_mouse_button_callback); } nk_init_default(&glfw.ctx, 0); - glfw.ctx.clip.copy = nk_glfw3_clipbard_copy; - glfw.ctx.clip.paste = nk_glfw3_clipbard_paste; + glfw.ctx.clip.copy = nk_glfw3_clipboard_copy; + glfw.ctx.clip.paste = nk_glfw3_clipboard_paste; glfw.ctx.clip.userdata = nk_handle_ptr(0); nk_buffer_init_default(&glfw.ogl.cmds); diff --git a/docs/extra.css b/docs/extra.css index 03a7f259..97ce33d0 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 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,.markdownTable code{background:none}#titlearea,.footer,.contents,div.header,.memdoc,table.doxtable td,table.doxtable th,table.markdownTable td,table.markdownTable 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,table.markdownTable code{padding:0}#nav-path,.directory .levels,span.lineno{display:none}html,#titlearea,.footer,tr.even,.directory tr.even,.doxtable tr:nth-child(even),tr.markdownTableBody:nth-child(even),.mdescLeft,.mdescRight,.memItemLeft,.memItemRight,code,.markdownTableRowEven{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("https://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,table.markdownTable 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,table.markdownTable{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} +.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,.markdownTable code{background:none}#titlearea,.footer,.contents,div.header,.memdoc,table.doxtable td,table.doxtable th,table.markdownTable td,table.markdownTable 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,table.markdownTable code{padding:0}#nav-path,.directory .levels,span.lineno{display:none}html,#titlearea,.footer,tr.even,.directory tr.even,.doxtable tr:nth-child(even),tr.markdownTableBody:nth-child(even),.mdescLeft,.mdescRight,.memItemLeft,.memItemRight,code,.markdownTableRowEven{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;min-height:64px;max-width:920px;padding:0 32px;margin:0 auto;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:center;align-content:stretch}#glfwhome{line-height:64px;padding-right:48px;color:#666;font-size:2.5em;background:url("https://www.glfw.org/css/arrow.png") no-repeat right}.glfwnavbar{list-style-type:none;margin:0 0 0 auto;float:right}#glfwhome,.glfwnavbar li{float:left}.glfwnavbar a,.glfwnavbar a:visited{line-height:64px;margin-left:2em;display:block;color:#666}.glfwnavbar{padding-left:0}#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;margin:0 auto;font-size:13px}#main-menu{max-width:920px;margin:0 auto;font-size:13px}.memtitle{display:none}.memproto,.memname{font-weight:bold;text-shadow:none}#main-menu{min-height:36px;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:center;align-content:stretch}#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}#main-menu>li:last-child{margin:0 0 0 auto}.contents{min-height:590px}div.contents,div.header{max-width:920px;margin:0 auto;padding:0 32px;background:#fff none}table.doxtable th,table.markdownTable 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,table.markdownTable{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 6d82b346..8972c113 100644 --- a/docs/extra.less +++ b/docs/extra.less @@ -159,11 +159,17 @@ h3 { .glfwheader { font-size:16px; - height:64px; + min-height:64px; max-width:920px; - min-width:800px; padding:0 32px; margin:0 auto; + + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: flex-start; + align-items: center; + align-content: stretch; } #glfwhome { @@ -176,7 +182,7 @@ h3 { .glfwnavbar { list-style-type:none; - margin:0 auto; + margin:0 0 0 auto; float:right; } @@ -191,6 +197,10 @@ h3 { color:@header-footer-link-color; } +.glfwnavbar { + padding-left: 0; +} + #glfwhome,.glfwnavbar a,.glfwnavbar a:visited { transition:.35s ease; } @@ -211,14 +221,12 @@ address.footer { #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; } @@ -233,9 +241,13 @@ address.footer { } #main-menu { - height:36px; - display:block; - position:relative; + min-height:36px; + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: flex-start; + align-items: center; + align-content: stretch; } #main-menu a,#main-menu a:visited,#main-menu a:hover,#main-menu li { @@ -250,6 +262,10 @@ address.footer { color:@default-link-color; } +#main-menu > li:last-child { + margin: 0 0 0 auto; +} + .contents { min-height:590px; } diff --git a/docs/header.html b/docs/header.html index f42f49ee..4cefa3d0 100644 --- a/docs/header.html +++ b/docs/header.html @@ -1,7 +1,8 @@ - - + + + $projectname: $title diff --git a/docs/input.dox b/docs/input.dox index 331f9718..5c6bbf03 100644 --- a/docs/input.dox +++ b/docs/input.dox @@ -550,10 +550,10 @@ int present = glfwJoystickPresent(GLFW_JOYSTICK_1); Each joystick has zero or more axes, zero or more buttons, zero or more hats, a human-readable name, a user pointer and an SDL compatible GUID. -When GLFW is initialized, detected joysticks are added to the beginning of -the array. Once a joystick is detected, it keeps its assigned ID until it is -disconnected or the library is terminated, so as joysticks are connected and -disconnected, there may appear gaps in the IDs. +Detected joysticks are added to the beginning of the array. Once a joystick is +detected, it keeps its assigned ID until it is disconnected or the library is +terminated, so as joysticks are connected and disconnected, there may appear +gaps in the IDs. Joystick axis, button and hat state is updated when polled and does not require a window to be created or events to be processed. However, if you want joystick @@ -648,7 +648,7 @@ const char* name = glfwGetJoystickName(GLFW_JOYSTICK_4); @endcode Joystick names are not guaranteed to be unique. Two joysticks of the same model -and make may have the same name. Only the [joystick token](@ref joysticks) is +and make may have the same name. Only the [joystick ID](@ref joysticks) is guaranteed to be unique, and only until that joystick is disconnected. diff --git a/docs/intro.dox b/docs/intro.dox index 1d041ae6..efc7c34c 100644 --- a/docs/intro.dox +++ b/docs/intro.dox @@ -22,8 +22,8 @@ There are also guides for the other areas of GLFW. Before most GLFW functions may be called, the library must be initialized. This initialization checks what features are available on the machine, -enumerates monitors and joysticks, initializes the timer and performs any -required platform-specific initialization. +enumerates monitors, initializes the timer and performs any required +platform-specific initialization. Only the following functions may be called before the library has been successfully initialized, and only from the main thread. diff --git a/docs/moving.dox b/docs/moving.dox index 85ba0a70..b80d84a2 100644 --- a/docs/moving.dox +++ b/docs/moving.dox @@ -362,8 +362,8 @@ should be using the character callback instead, on both GLFW 2 and 3. This will give you the characters being input, as opposed to the keys being pressed. GLFW 3 has key tokens for all keys on a standard 105 key keyboard, so instead of -having to remember whether to check for `'a'` or `'A'`, you now check for -`GLFW_KEY_A`. +having to remember whether to check for `a` or `A`, you now check for +@ref GLFW_KEY_A. @subsection moving_joystick Joystick function changes diff --git a/docs/news.dox b/docs/news.dox index fccd4166..19df848a 100644 --- a/docs/news.dox +++ b/docs/news.dox @@ -27,6 +27,14 @@ are still available. For more information see @ref cursor_standard. +@subsubsection mouse_passthrough_34 Mouse event passthrough + +GLFW now provides the [GLFW_MOUSE_PASSTHROUGH](@ref GLFW_MOUSE_PASSTHROUGH_hint) +window hint for making a window transparent to mouse input, lettings events pass +to whatever window is behind it. This can also be changed after window +creation with the matching [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib). + + @subsubsection features_34_angle_backend Support for ANGLE rendering backend selection GLFW now provides the @@ -47,6 +55,21 @@ applications. @subsection caveats_34 Caveats for version 3.4 +@subsubsection joysticks_34 Joystick support is initialized on demand + +The joystick part of GLFW is now initialized when first used, primarily to work +around faulty Windows drivers that cause DirectInput to take up to several +seconds to enumerate devices. + +This change will usually not be observable. However, if your application waits +for events without having first called any joystick function or created any +visible windows, the wait may never unblock as GLFW may not yet have subscribed +to joystick related OS events. + +To work around this, call any joystick function before waiting for events, for +example by setting a [joystick callback](@ref joystick_event). + + @subsubsection standalone_34 Tests and examples are disabled when built as a sub-project GLFW now does not build the tests and examples when it is added as @@ -74,6 +97,13 @@ GLFW no longer depends on the CoreVideo framework on macOS and it no longer needs to be specified during compilation or linking. +@subsubsection caveat_fbtransparency_34 Framebuffer transparency requires DWM transparency + +GLFW no longer supports framebuffer transparency enabled via @ref +GLFW_TRANSPARENT_FRAMEBUFFER on Windows 7 if DWM transparency is off +(the Transparency setting under Personalization > Window Color). + + @subsection deprecations_34 Deprecations in version 3.4 @subsection removals_34 Removals in 3.4 @@ -97,6 +127,7 @@ then GLFW will fail to initialize. - @ref GLFW_RESIZE_NWSE_CURSOR - @ref GLFW_RESIZE_NESW_CURSOR - @ref GLFW_RESIZE_ALL_CURSOR + - @ref GLFW_MOUSE_PASSTHROUGH - @ref GLFW_NOT_ALLOWED_CURSOR - @ref GLFW_CURSOR_UNAVAILABLE - @ref GLFW_WIN32_KEYBOARD_MENU diff --git a/docs/window.dox b/docs/window.dox index ddd75147..0eb2b24a 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -234,13 +234,6 @@ alpha channel will be used to combine the framebuffer with the background. This does not affect window decorations. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. -@par -@win32 GLFW sets a color key for the window to work around repainting issues -with a transparent framebuffer. The chosen color value is RGB 255,0,255 -(magenta). This will make pixels with that exact color fully transparent -regardless of their alpha values. If this is a problem, make these pixels any -other color before buffer swap. - @anchor GLFW_FOCUS_ON_SHOW_hint __GLFW_FOCUS_ON_SHOW__ specifies whether the window will be given input focus when @ref glfwShowWindow is called. Possible values are `GLFW_TRUE` and `GLFW_FALSE`. @@ -255,6 +248,13 @@ This hint only has an effect on platforms where screen coordinates and pixels always map 1:1 such as Windows and X11. On platforms like macOS the resolution of the framebuffer is changed independently of the window size. +@anchor GLFW_MOUSE_PASSTHROUGH_hint +__GLFW_MOUSE_PASSTHROUGH__ specifies whether the window is transparent to mouse +input, letting any mouse events pass through to whatever window is behind it. +This is only supported for undecorated windows. Decorated windows with this +enabled will behave differently between platforms. Possible values are +`GLFW_TRUE` and `GLFW_FALSE`. + @subsubsection window_hints_fb Framebuffer related hints @@ -416,6 +416,10 @@ Debug contexts for OpenGL and OpenGL ES are described in detail by the [GL_KHR_debug](https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_debug.txt) extension. +@par +This is the new name, introduced in GLFW 3.4. The older +`GLFW_OPENGL_DEBUG_CONTEXT` name is also available for compatibility. + @anchor GLFW_OPENGL_PROFILE_hint __GLFW_OPENGL_PROFILE__ specifies which OpenGL profile to create the context for. Possible values are one of `GLFW_OPENGL_CORE_PROFILE` or @@ -523,6 +527,7 @@ GLFW_CENTER_CURSOR | `GLFW_TRUE` | `GLFW_TRUE` or `GL GLFW_TRANSPARENT_FRAMEBUFFER | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_FOCUS_ON_SHOW | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_SCALE_TO_MONITOR | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` +GLFW_MOUSE_PASSTHROUGH | `GLFW_FALSE` | `GLFW_TRUE` or `GLFW_FALSE` GLFW_RED_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` GLFW_GREEN_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` GLFW_BLUE_BITS | 8 | 0 to `INT_MAX` or `GLFW_DONT_CARE` @@ -1223,7 +1228,11 @@ If the system does not support whole window transparency, this function always returns one. GLFW comes with a test program that lets you control whole window transparency -at run-time called `opacity`. +at run-time called `window`. + +If you want to use either of these transparency methods to display a temporary +overlay like for example a notification, the @ref GLFW_FLOATING and @ref +GLFW_MOUSE_PASSTHROUGH window hints and attributes may be useful. @subsection window_attribs Window attributes @@ -1313,6 +1322,15 @@ focus when @ref glfwShowWindow is called. This can be set before creation with the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint or after with @ref glfwSetWindowAttrib. +@anchor GLFW_MOUSE_PASSTHROUGH_attrib +__GLFW_MOUSE_PASSTHROUGH__ specifies whether the window is transparent to mouse +input, letting any mouse events pass through to whatever window is behind it. +This can be set before creation with the +[GLFW_MOUSE_PASSTHROUGH](@ref GLFW_MOUSE_PASSTHROUGH_hint) window hint or after +with @ref glfwSetWindowAttrib. This is only supported for undecorated windows. +Decorated windows with this enabled will behave differently between platforms. + + @subsubsection window_attribs_ctx Context related attributes @anchor GLFW_CLIENT_API_attrib @@ -1344,6 +1362,10 @@ OpenGL forward-compatible one, or `GLFW_FALSE` otherwise. __GLFW_CONTEXT_DEBUG__ is `GLFW_TRUE` if the window's context is in debug mode, or `GLFW_FALSE` otherwise. +@par +This is the new name, introduced in GLFW 3.4. The older +`GLFW_OPENGL_DEBUG_CONTEXT` name is also available for compatibility. + @anchor GLFW_OPENGL_PROFILE_attrib __GLFW_OPENGL_PROFILE__ indicates the OpenGL profile used by the context. This is `GLFW_OPENGL_CORE_PROFILE` or `GLFW_OPENGL_COMPAT_PROFILE` if the context diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 87d0cbc8..21ba4838 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -33,6 +33,7 @@ add_executable(sharing WIN32 MACOSX_BUNDLE sharing.c ${ICON} ${GLAD_GL}) add_executable(splitview WIN32 MACOSX_BUNDLE splitview.c ${ICON} ${GLAD_GL}) add_executable(triangle-opengl WIN32 MACOSX_BUNDLE triangle-opengl.c ${ICON} ${GLAD_GL}) add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD_GL}) +add_executable(windows WIN32 MACOSX_BUNDLE windows.c ${ICON} ${GLAD_GL}) target_link_libraries(particles Threads::Threads) if (RT_LIBRARY) @@ -40,7 +41,7 @@ if (RT_LIBRARY) endif() set(GUI_ONLY_BINARIES boing gears heightmap particles sharing splitview - triangle-opengl wave) + triangle-opengl wave windows) set(CONSOLE_BINARIES offscreen) set_target_properties(${GUI_ONLY_BINARIES} ${CONSOLE_BINARIES} PROPERTIES @@ -67,6 +68,7 @@ if (APPLE) set_target_properties(triangle-opengl PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "OpenGL Triangle") set_target_properties(splitview PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "SplitView") set_target_properties(wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave") + set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows") set_source_files_properties(glfw.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") diff --git a/tests/windows.c b/examples/windows.c similarity index 52% rename from tests/windows.c rename to examples/windows.c index 881338fb..94f3ccbc 100644 --- a/tests/windows.c +++ b/examples/windows.c @@ -1,5 +1,5 @@ //======================================================================== -// Simple multi-window test +// Simple multi-window example // Copyright (c) Camilla Löwy // // This software is provided 'as-is', without any express or implied @@ -22,10 +22,6 @@ // distribution. // //======================================================================== -// -// This test creates four windows and clears each in a different color -// -//======================================================================== #include #define GLFW_INCLUDE_NONE @@ -34,109 +30,60 @@ #include #include -static GLFWwindow* windows[4]; -static const char* titles[] = -{ - "Red", - "Green", - "Blue", - "Yellow" -}; - -static const struct -{ - float r, g, b; -} colors[] = -{ - { 0.95f, 0.32f, 0.11f }, - { 0.50f, 0.80f, 0.16f }, - { 0.f, 0.68f, 0.94f }, - { 0.98f, 0.74f, 0.04f } -}; - -static void error_callback(int error, const char* description) -{ - fprintf(stderr, "Error: %s\n", description); -} - -static void arrange_windows(void) -{ - int xbase, ybase; - glfwGetWindowPos(windows[0], &xbase, &ybase); - - for (int i = 0; i < 4; i++) - { - int left, top, right, bottom; - glfwGetWindowFrameSize(windows[i], &left, &top, &right, &bottom); - glfwSetWindowPos(windows[i], - xbase + (i & 1) * (200 + left + right), - ybase + (i >> 1) * (200 + top + bottom)); - } -} - -static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) -{ - if (action != GLFW_PRESS) - return; - - switch (key) - { - case GLFW_KEY_SPACE: - { - int xpos, ypos; - glfwGetWindowPos(window, &xpos, &ypos); - glfwSetWindowPos(window, xpos, ypos); - break; - } - - case GLFW_KEY_ESCAPE: - glfwSetWindowShouldClose(window, GLFW_TRUE); - break; - - case GLFW_KEY_D: - { - for (int i = 0; i < 4; i++) - { - const int decorated = glfwGetWindowAttrib(windows[i], GLFW_DECORATED); - glfwSetWindowAttrib(windows[i], GLFW_DECORATED, !decorated); - } - - arrange_windows(); - break; - } - } -} - int main(int argc, char** argv) { - glfwSetErrorCallback(error_callback); + int xpos, ypos, height; + const char* description; + GLFWwindow* windows[4]; if (!glfwInit()) + { + glfwGetError(&description); + printf("Error: %s\n", description); exit(EXIT_FAILURE); + } glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); + glfwWindowHint(GLFW_DECORATED, GLFW_FALSE); + + glfwGetMonitorWorkarea(glfwGetPrimaryMonitor(), &xpos, &ypos, NULL, &height); for (int i = 0; i < 4; i++) { + const int size = height / 5; + const struct + { + float r, g, b; + } colors[] = + { + { 0.95f, 0.32f, 0.11f }, + { 0.50f, 0.80f, 0.16f }, + { 0.f, 0.68f, 0.94f }, + { 0.98f, 0.74f, 0.04f } + }; + if (i > 0) glfwWindowHint(GLFW_FOCUS_ON_SHOW, GLFW_FALSE); - windows[i] = glfwCreateWindow(200, 200, titles[i], NULL, NULL); + windows[i] = glfwCreateWindow(size, size, "Multi-Window Example", NULL, NULL); if (!windows[i]) { + glfwGetError(&description); + printf("Error: %s\n", description); glfwTerminate(); exit(EXIT_FAILURE); } - glfwSetKeyCallback(windows[i], key_callback); + glfwSetWindowPos(windows[i], + xpos + size * (1 + (i & 1)), + ypos + size * (1 + (i >> 1))); + glfwSetInputMode(windows[i], GLFW_STICKY_KEYS, GLFW_TRUE); glfwMakeContextCurrent(windows[i]); gladLoadGL(glfwGetProcAddress); glClearColor(colors[i].r, colors[i].g, colors[i].b, 1.f); } - arrange_windows(); - for (int i = 0; i < 4; i++) glfwShowWindow(windows[i]); @@ -148,7 +95,8 @@ int main(int argc, char** argv) glClear(GL_COLOR_BUFFER_BIT); glfwSwapBuffers(windows[i]); - if (glfwWindowShouldClose(windows[i])) + if (glfwWindowShouldClose(windows[i]) || + glfwGetKey(windows[i], GLFW_KEY_ESCAPE)) { glfwTerminate(); exit(EXIT_SUCCESS); diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index a25f4144..18c186c0 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -895,6 +895,13 @@ extern "C" { */ #define GLFW_FOCUS_ON_SHOW 0x0002000C +/*! @brief Mouse input transparency window hint and attribute + * + * Mouse input transparency [window hint](@ref GLFW_MOUSE_PASSTHROUGH_hint) or + * [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib). + */ +#define GLFW_MOUSE_PASSTHROUGH 0x0002000D + /*! @brief Framebuffer bit depth hint. * * Framebuffer bit depth [hint](@ref GLFW_RED_BITS). @@ -3668,6 +3675,7 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib); * [GLFW_FLOATING](@ref GLFW_FLOATING_attrib), * [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib). + * [GLFW_MOUSE_PASSTHROUGH](@ref GLFW_MOUSE_PASSTHROUGH_attrib) * * Some of these attributes are ignored for full screen windows. The new * value will take effect if the window is later made windowed. diff --git a/src/cocoa_init.m b/src/cocoa_init.m index 434e5beb..7cad8b8e 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -551,7 +551,6 @@ int _glfwPlatformInit(void) return GLFW_FALSE; _glfwInitTimerNS(); - _glfwInitJoysticksNS(); _glfwPollMonitorsNS(); @@ -605,7 +604,6 @@ void _glfwPlatformTerminate(void) free(_glfw.ns.clipboardString); _glfwTerminateNSGL(); - _glfwTerminateJoysticksNS(); } // autoreleasepool } diff --git a/src/cocoa_joystick.h b/src/cocoa_joystick.h index 9bf5cde4..23d2b86a 100644 --- a/src/cocoa_joystick.h +++ b/src/cocoa_joystick.h @@ -44,7 +44,3 @@ typedef struct _GLFWjoystickNS CFMutableArrayRef hats; } _GLFWjoystickNS; - -void _glfwInitJoysticksNS(void); -void _glfwTerminateJoysticksNS(void); - diff --git a/src/cocoa_joystick.m b/src/cocoa_joystick.m index 88636a87..4a64fb09 100644 --- a/src/cocoa_joystick.m +++ b/src/cocoa_joystick.m @@ -304,12 +304,10 @@ static void removeCallback(void* context, ////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// +////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -// Initialize joystick interface -// -void _glfwInitJoysticksNS(void) +GLFWbool _glfwPlatformInitJoysticks(void) { CFMutableArrayRef matching; const long usages[] = @@ -328,7 +326,7 @@ void _glfwInitJoysticksNS(void) if (!matching) { _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create array"); - return; + return GLFW_FALSE; } for (size_t i = 0; i < sizeof(usages) / sizeof(long); i++) @@ -383,26 +381,24 @@ void _glfwInitJoysticksNS(void) // Execute the run loop once in order to register any initially-attached // joysticks CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false); + return GLFW_TRUE; } -// Close all opened joystick handles -// -void _glfwTerminateJoysticksNS(void) +void _glfwPlatformTerminateJoysticks(void) { int jid; for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) closeJoystick(_glfw.joysticks + jid); - CFRelease(_glfw.ns.hidManager); - _glfw.ns.hidManager = NULL; + if (_glfw.ns.hidManager) + { + CFRelease(_glfw.ns.hidManager); + _glfw.ns.hidManager = NULL; + } } -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) { if (mode & _GLFW_POLL_AXES) diff --git a/src/cocoa_monitor.m b/src/cocoa_monitor.m index 42f2dce2..2bb83738 100644 --- a/src/cocoa_monitor.m +++ b/src/cocoa_monitor.m @@ -277,14 +277,20 @@ static double getFallbackRefreshRate(CGDirectDisplayID displayID) CFSTR("IOFBCurrentPixelCount"), kCFAllocatorDefault, kNilOptions); - if (!clockRef || !countRef) - break; uint32_t clock = 0, count = 0; - CFNumberGetValue(clockRef, kCFNumberIntType, &clock); - CFNumberGetValue(countRef, kCFNumberIntType, &count); - CFRelease(clockRef); - CFRelease(countRef); + + if (clockRef) + { + CFNumberGetValue(clockRef, kCFNumberIntType, &clock); + CFRelease(clockRef); + } + + if (countRef) + { + CFNumberGetValue(countRef, kCFNumberIntType, &count); + CFRelease(countRef); + } if (clock > 0 && count > 0) refreshRate = clock / (double) count; diff --git a/src/cocoa_window.m b/src/cocoa_window.m index e7d048a9..dc3161e7 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1371,6 +1371,13 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) } // autoreleasepool } +void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled) +{ + @autoreleasepool { + [window->ns.object setIgnoresMouseEvents:enabled]; + } +} + float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) { @autoreleasepool { diff --git a/src/init.c b/src/init.c index 5df22d0e..e0ee6705 100644 --- a/src/init.c +++ b/src/init.c @@ -91,6 +91,7 @@ static void terminate(void) _glfw.mappingCount = 0; _glfwTerminateVulkan(); + _glfwPlatformTerminateJoysticks(); _glfwPlatformTerminate(); _glfw.initialized = GLFW_FALSE; diff --git a/src/input.c b/src/input.c index f6163093..226f835d 100644 --- a/src/input.c +++ b/src/input.c @@ -43,6 +43,22 @@ #define _GLFW_JOYSTICK_BUTTON 2 #define _GLFW_JOYSTICK_HATBIT 3 +// Initializes the platform joystick API if it has not been already +// +static GLFWbool initJoysticks(void) +{ + if (!_glfw.joysticksInitialized) + { + if (!_glfwPlatformInitJoysticks()) + { + _glfwPlatformTerminateJoysticks(); + return GLFW_FALSE; + } + } + + return _glfw.joysticksInitialized = GLFW_TRUE; +} + // Finds a mapping based on joystick GUID // static _GLFWmapping* findMapping(const char* guid) @@ -929,6 +945,9 @@ GLFWAPI int glfwJoystickPresent(int jid) return GLFW_FALSE; } + if (!initJoysticks()) + return GLFW_FALSE; + js = _glfw.joysticks + jid; if (!js->present) return GLFW_FALSE; @@ -954,6 +973,9 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count) return NULL; } + if (!initJoysticks()) + return NULL; + js = _glfw.joysticks + jid; if (!js->present) return NULL; @@ -983,6 +1005,9 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count) return NULL; } + if (!initJoysticks()) + return NULL; + js = _glfw.joysticks + jid; if (!js->present) return NULL; @@ -1016,6 +1041,9 @@ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count) return NULL; } + if (!initJoysticks()) + return NULL; + js = _glfw.joysticks + jid; if (!js->present) return NULL; @@ -1042,6 +1070,9 @@ GLFWAPI const char* glfwGetJoystickName(int jid) return NULL; } + if (!initJoysticks()) + return NULL; + js = _glfw.joysticks + jid; if (!js->present) return NULL; @@ -1067,6 +1098,9 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid) return NULL; } + if (!initJoysticks()) + return NULL; + js = _glfw.joysticks + jid; if (!js->present) return NULL; @@ -1112,6 +1146,10 @@ GLFWAPI void* glfwGetJoystickUserPointer(int jid) GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + + if (!initJoysticks()) + return NULL; + _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun); return cbfun; } @@ -1191,6 +1229,9 @@ GLFWAPI int glfwJoystickIsGamepad(int jid) return GLFW_FALSE; } + if (!initJoysticks()) + return GLFW_FALSE; + js = _glfw.joysticks + jid; if (!js->present) return GLFW_FALSE; @@ -1216,6 +1257,9 @@ GLFWAPI const char* glfwGetGamepadName(int jid) return NULL; } + if (!initJoysticks()) + return NULL; + js = _glfw.joysticks + jid; if (!js->present) return NULL; @@ -1248,6 +1292,9 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state) return GLFW_FALSE; } + if (!initJoysticks()) + return GLFW_FALSE; + js = _glfw.joysticks + jid; if (!js->present) return GLFW_FALSE; diff --git a/src/internal.h b/src/internal.h index ab6c9471..a30e98ee 100644 --- a/src/internal.h +++ b/src/internal.h @@ -273,6 +273,7 @@ struct _GLFWwndconfig GLFWbool maximized; GLFWbool centerCursor; GLFWbool focusOnShow; + GLFWbool mousePassthrough; GLFWbool scaleToMonitor; struct { GLFWbool retina; @@ -401,6 +402,7 @@ struct _GLFWwindow GLFWbool autoIconify; GLFWbool floating; GLFWbool focusOnShow; + GLFWbool mousePassthrough; GLFWbool shouldClose; void* userPointer; GLFWvidmode videoMode; @@ -558,6 +560,7 @@ struct _GLFWlibrary _GLFWmonitor** monitors; int monitorCount; + GLFWbool joysticksInitialized; _GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1]; _GLFWmapping* mappings; int mappingCount; @@ -652,6 +655,8 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) void _glfwPlatformSetClipboardString(const char* string); const char* _glfwPlatformGetClipboardString(void); +GLFWbool _glfwPlatformInitJoysticks(void); +void _glfwPlatformTerminateJoysticks(void); int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode); void _glfwPlatformUpdateGamepadGUID(char* guid); @@ -700,6 +705,7 @@ float _glfwPlatformGetWindowOpacity(_GLFWwindow* window); void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled); +void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled); void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity); void _glfwPlatformPollEvents(void); diff --git a/src/linux_joystick.c b/src/linux_joystick.c index 1f9b35fe..122bc66a 100644 --- a/src/linux_joystick.c +++ b/src/linux_joystick.c @@ -264,9 +264,50 @@ static int compareJoysticks(const void* fp, const void* sp) ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// -// Initialize joystick interface -// -GLFWbool _glfwInitJoysticksLinux(void) +void _glfwDetectJoystickConnectionLinux(void) +{ + if (_glfw.linjs.inotify <= 0) + return; + + ssize_t offset = 0; + char buffer[16384]; + const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer)); + + while (size > offset) + { + regmatch_t match; + const struct inotify_event* e = (struct inotify_event*) (buffer + offset); + + offset += sizeof(struct inotify_event) + e->len; + + if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0) + continue; + + char path[PATH_MAX]; + snprintf(path, sizeof(path), "/dev/input/%s", e->name); + + if (e->mask & (IN_CREATE | IN_ATTRIB)) + openJoystickDevice(path); + else if (e->mask & IN_DELETE) + { + for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) + { + if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0) + { + closeJoystick(_glfw.joysticks + jid); + break; + } + } + } + } +} + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + +GLFWbool _glfwPlatformInitJoysticks(void) { const char* dirname = "/dev/input"; @@ -320,9 +361,7 @@ GLFWbool _glfwInitJoysticksLinux(void) return GLFW_TRUE; } -// Close all opened joystick handles -// -void _glfwTerminateJoysticksLinux(void) +void _glfwPlatformTerminateJoysticks(void) { int jid; @@ -333,60 +372,16 @@ void _glfwTerminateJoysticksLinux(void) closeJoystick(js); } - regfree(&_glfw.linjs.regex); - if (_glfw.linjs.inotify > 0) { if (_glfw.linjs.watch > 0) inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch); close(_glfw.linjs.inotify); + regfree(&_glfw.linjs.regex); } } -void _glfwDetectJoystickConnectionLinux(void) -{ - if (_glfw.linjs.inotify <= 0) - return; - - ssize_t offset = 0; - char buffer[16384]; - const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer)); - - while (size > offset) - { - regmatch_t match; - const struct inotify_event* e = (struct inotify_event*) (buffer + offset); - - offset += sizeof(struct inotify_event) + e->len; - - if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0) - continue; - - char path[PATH_MAX]; - snprintf(path, sizeof(path), "/dev/input/%s", e->name); - - if (e->mask & (IN_CREATE | IN_ATTRIB)) - openJoystickDevice(path); - else if (e->mask & IN_DELETE) - { - for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) - { - if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0) - { - closeJoystick(_glfw.joysticks + jid); - break; - } - } - } - } -} - - -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) { // Read all queued events (non-blocking) diff --git a/src/linux_joystick.h b/src/linux_joystick.h index 7373f130..05d5488f 100644 --- a/src/linux_joystick.h +++ b/src/linux_joystick.h @@ -55,8 +55,5 @@ typedef struct _GLFWlibraryLinux GLFWbool dropped; } _GLFWlibraryLinux; - -GLFWbool _glfwInitJoysticksLinux(void); -void _glfwTerminateJoysticksLinux(void); void _glfwDetectJoystickConnectionLinux(void); diff --git a/src/null_joystick.c b/src/null_joystick.c index 36c18aa2..27756a61 100644 --- a/src/null_joystick.c +++ b/src/null_joystick.c @@ -33,6 +33,15 @@ ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// +GLFWbool _glfwPlatformInitJoysticks(void) +{ + return GLFW_TRUE; +} + +void _glfwPlatformTerminateJoysticks(void) +{ +} + int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) { return GLFW_FALSE; diff --git a/src/null_monitor.c b/src/null_monitor.c index 7271e810..8301eb3a 100644 --- a/src/null_monitor.c +++ b/src/null_monitor.c @@ -72,6 +72,10 @@ void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor) void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos) { + if (xpos) + *xpos = 0; + if (ypos) + *ypos = 0; } void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, @@ -90,9 +94,9 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, const GLFWvidmode mode = getVideoMode(); if (xpos) - *xpos = 10; + *xpos = 0; if (ypos) - ypos = 0; + *ypos = 10; if (width) *width = mode.width; if (height) diff --git a/src/null_window.c b/src/null_window.c index 1f760e84..6e0b9408 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -269,10 +269,25 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, { if (window->null.decorated && !window->monitor) { - *left = 1; - *top = 10; - *right = 1; - *bottom = 1; + if (left) + *left = 1; + if (top) + *top = 10; + if (right) + *right = 1; + if (bottom) + *bottom = 1; + } + else + { + if (left) + *left = 0; + if (top) + *top = 0; + if (right) + *right = 0; + if (bottom) + *bottom = 0; } } @@ -362,6 +377,10 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) window->null.floating = enabled; } +void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled) +{ +} + float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) { return window->null.opacity; diff --git a/src/win32_init.c b/src/win32_init.c index 260e888e..f6995e51 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -143,6 +143,8 @@ static GLFWbool loadLibraries(void) GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush"); _glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow) GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow"); + _glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor) + GetProcAddress(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor"); } _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll"); @@ -580,7 +582,6 @@ int _glfwPlatformInit(void) return GLFW_FALSE; _glfwInitTimerWin32(); - _glfwInitJoysticksWin32(); _glfwPollMonitorsWin32(); return GLFW_TRUE; @@ -607,8 +608,6 @@ void _glfwPlatformTerminate(void) _glfwTerminateWGL(); _glfwTerminateEGL(); - _glfwTerminateJoysticksWin32(); - freeLibraries(); } diff --git a/src/win32_joystick.c b/src/win32_joystick.c index 49187dab..9c71d114 100644 --- a/src/win32_joystick.c +++ b/src/win32_joystick.c @@ -491,39 +491,6 @@ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user) ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// -// Initialize joystick interface -// -void _glfwInitJoysticksWin32(void) -{ - if (_glfw.win32.dinput8.instance) - { - if (FAILED(DirectInput8Create(GetModuleHandle(NULL), - DIRECTINPUT_VERSION, - &IID_IDirectInput8W, - (void**) &_glfw.win32.dinput8.api, - NULL))) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Win32: Failed to create interface"); - } - } - - _glfwDetectJoystickConnectionWin32(); -} - -// Close all opened joystick handles -// -void _glfwTerminateJoysticksWin32(void) -{ - int jid; - - for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++) - closeJoystick(_glfw.joysticks + jid); - - if (_glfw.win32.dinput8.api) - IDirectInput8_Release(_glfw.win32.dinput8.api); -} - // Checks for new joysticks after DBT_DEVICEARRIVAL // void _glfwDetectJoystickConnectionWin32(void) @@ -603,6 +570,37 @@ void _glfwDetectJoystickDisconnectionWin32(void) ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// +GLFWbool _glfwPlatformInitJoysticks(void) +{ + if (_glfw.win32.dinput8.instance) + { + if (FAILED(DirectInput8Create(GetModuleHandle(NULL), + DIRECTINPUT_VERSION, + &IID_IDirectInput8W, + (void**) &_glfw.win32.dinput8.api, + NULL))) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Win32: Failed to create interface"); + return GLFW_FALSE; + } + } + + _glfwDetectJoystickConnectionWin32(); + return GLFW_TRUE; +} + +void _glfwPlatformTerminateJoysticks(void) +{ + int jid; + + for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++) + closeJoystick(_glfw.joysticks + jid); + + if (_glfw.win32.dinput8.api) + IDirectInput8_Release(_glfw.win32.dinput8.api); +} + int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) { if (js->win32.device) diff --git a/src/win32_joystick.h b/src/win32_joystick.h index f593274e..b6a7adc3 100644 --- a/src/win32_joystick.h +++ b/src/win32_joystick.h @@ -48,9 +48,6 @@ typedef struct _GLFWjoystickWin32 GUID guid; } _GLFWjoystickWin32; - -void _glfwInitJoysticksWin32(void); -void _glfwTerminateJoysticksWin32(void); void _glfwDetectJoystickConnectionWin32(void); void _glfwDetectJoystickDisconnectionWin32(void); diff --git a/src/win32_platform.h b/src/win32_platform.h index 76ea609a..260a77ff 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -77,6 +77,9 @@ #ifndef WM_DWMCOMPOSITIONCHANGED #define WM_DWMCOMPOSITIONCHANGED 0x031E #endif +#ifndef WM_DWMCOLORIZATIONCOLORCHANGED + #define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320 +#endif #ifndef WM_COPYGLOBALDATA #define WM_COPYGLOBALDATA 0x0049 #endif @@ -244,9 +247,11 @@ typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UIN typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*); typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID); typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*); +typedef HRESULT (WINAPI * PFN_DwmGetColorizationColor)(DWORD*,BOOL*); #define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled #define DwmFlush _glfw.win32.dwmapi.Flush #define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow +#define DwmGetColorizationColor _glfw.win32.dwmapi.GetColorizationColor // shcore.dll function pointer typedefs typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS); @@ -368,6 +373,7 @@ typedef struct _GLFWlibraryWin32 PFN_DwmIsCompositionEnabled IsCompositionEnabled; PFN_DwmFlush Flush; PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow; + PFN_DwmGetColorizationColor GetColorizationColor; } dwmapi; struct { diff --git a/src/win32_window.c b/src/win32_window.c index fe75b765..30d9b444 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -377,12 +377,17 @@ static void updateWindowStyles(const _GLFWwindow* window) // static void updateFramebufferTransparency(const _GLFWwindow* window) { - BOOL enabled; + BOOL composition, opaque; + DWORD color; if (!IsWindowsVistaOrGreater()) return; - if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled) + if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition) + return; + + if (IsWindows8OrGreater() || + (SUCCEEDED(DwmGetColorizationColor(&color, &opaque)) && !opaque)) { HRGN region = CreateRectRgn(0, 0, -1, -1); DWM_BLURBEHIND bb = {0}; @@ -390,37 +395,18 @@ static void updateFramebufferTransparency(const _GLFWwindow* window) bb.hRgnBlur = region; bb.fEnable = TRUE; - if (SUCCEEDED(DwmEnableBlurBehindWindow(window->win32.handle, &bb))) - { - // Decorated windows don't repaint the transparent background - // leaving a trail behind animations - // HACK: Making the window layered with a transparency color key - // seems to fix this. Normally, when specifying - // a transparency color key to be used when composing the - // layered window, all pixels painted by the window in this - // color will be transparent. That doesn't seem to be the - // case anymore, at least when used with blur behind window - // plus negative region. - LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE); - exStyle |= WS_EX_LAYERED; - SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle); - - // Using a color key not equal to black to fix the trailing - // issue. When set to black, something is making the hit test - // not resize with the window frame. - SetLayeredWindowAttributes(window->win32.handle, - RGB(255, 0, 255), 255, LWA_COLORKEY); - } - + DwmEnableBlurBehindWindow(window->win32.handle, &bb); DeleteObject(region); } else { - LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE); - exStyle &= ~WS_EX_LAYERED; - SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle); - RedrawWindow(window->win32.handle, NULL, NULL, - RDW_ERASE | RDW_INVALIDATE | RDW_FRAME); + // HACK: Disable framebuffer transparency on Windows 7 when the + // colorization color is opaque, because otherwise the window + // contents is blended additively with the previous frame instead + // of replacing it + DWM_BLURBEHIND bb = {0}; + bb.dwFlags = DWM_BB_ENABLE; + DwmEnableBlurBehindWindow(window->win32.handle, &bb); } } @@ -526,6 +512,9 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_DEVICECHANGE: { + if (!_glfw.joysticksInitialized) + break; + if (wParam == DBT_DEVICEARRIVAL) { DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; @@ -1101,6 +1090,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, } case WM_DWMCOMPOSITIONCHANGED: + case WM_DWMCOLORIZATIONCOLORCHANGED: { if (window->win32.transparent) updateFramebufferTransparency(window); @@ -1826,7 +1816,8 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window) int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) { - BOOL enabled; + BOOL composition, opaque; + DWORD color; if (!window->win32.transparent) return GLFW_FALSE; @@ -1834,7 +1825,20 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) if (!IsWindowsVistaOrGreater()) return GLFW_FALSE; - return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled; + if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition) + return GLFW_FALSE; + + if (!IsWindows8OrGreater()) + { + // HACK: Disable framebuffer transparency on Windows 7 when the + // colorization color is opaque, because otherwise the window + // contents is blended additively with the previous frame instead + // of replacing it + if (FAILED(DwmGetColorizationColor(&color, &opaque)) || opaque) + return GLFW_FALSE; + } + + return GLFW_TRUE; } void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled) @@ -1854,6 +1858,36 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); } +void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled) +{ + COLORREF key = 0; + BYTE alpha = 0; + DWORD flags = 0; + DWORD exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE); + + if (exStyle & WS_EX_LAYERED) + GetLayeredWindowAttributes(window->win32.handle, &key, &alpha, &flags); + + if (enabled) + exStyle |= (WS_EX_TRANSPARENT | WS_EX_LAYERED); + else + { + exStyle &= ~WS_EX_TRANSPARENT; + // NOTE: Window opacity also needs the layered window style so do not + // remove it if the window is alpha blended + if (exStyle & WS_EX_LAYERED) + { + if (!(flags & LWA_ALPHA)) + exStyle &= ~WS_EX_LAYERED; + } + } + + SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle); + + if (enabled) + SetLayeredWindowAttributes(window->win32.handle, key, alpha, flags); +} + float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) { BYTE alpha; @@ -1871,19 +1905,22 @@ float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) { - if (opacity < 1.f) + LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE); + if (opacity < 1.f || (exStyle & WS_EX_TRANSPARENT)) { const BYTE alpha = (BYTE) (255 * opacity); - DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE); - style |= WS_EX_LAYERED; - SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style); + exStyle |= WS_EX_LAYERED; + SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle); SetLayeredWindowAttributes(window->win32.handle, 0, alpha, LWA_ALPHA); } + else if (exStyle & WS_EX_TRANSPARENT) + { + SetLayeredWindowAttributes(window->win32.handle, 0, 0, 0); + } else { - DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE); - style &= ~WS_EX_LAYERED; - SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style); + exStyle &= ~WS_EX_LAYERED; + SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle); } } diff --git a/src/window.c b/src/window.c index 4716cd09..efcb4125 100644 --- a/src/window.c +++ b/src/window.c @@ -197,13 +197,14 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, window->videoMode.blueBits = fbconfig.blueBits; window->videoMode.refreshRate = _glfw.hints.refreshRate; - window->monitor = (_GLFWmonitor*) monitor; - window->resizable = wndconfig.resizable; - window->decorated = wndconfig.decorated; - window->autoIconify = wndconfig.autoIconify; - window->floating = wndconfig.floating; - window->focusOnShow = wndconfig.focusOnShow; - window->cursorMode = GLFW_CURSOR_NORMAL; + window->monitor = (_GLFWmonitor*) monitor; + window->resizable = wndconfig.resizable; + window->decorated = wndconfig.decorated; + window->autoIconify = wndconfig.autoIconify; + window->floating = wndconfig.floating; + window->focusOnShow = wndconfig.focusOnShow; + window->mousePassthrough = wndconfig.mousePassthrough; + window->cursorMode = GLFW_CURSOR_NORMAL; window->minwidth = GLFW_DONT_CARE; window->minheight = GLFW_DONT_CARE; @@ -228,6 +229,9 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, } } + if (wndconfig.mousePassthrough) + _glfwPlatformSetWindowMousePassthrough(window, GLFW_TRUE); + if (window->monitor) { if (wndconfig.centerCursor) @@ -378,6 +382,9 @@ GLFWAPI void glfwWindowHint(int hint, int value) case GLFW_FOCUS_ON_SHOW: _glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE; return; + case GLFW_MOUSE_PASSTHROUGH: + _glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE; + return; case GLFW_CLIENT_API: _glfw.hints.context.client = value; return; @@ -822,6 +829,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) return _glfwPlatformWindowHovered(window); case GLFW_FOCUS_ON_SHOW: return window->focusOnShow; + case GLFW_MOUSE_PASSTHROUGH: + return window->mousePassthrough; case GLFW_TRANSPARENT_FRAMEBUFFER: return _glfwPlatformFramebufferTransparent(window); case GLFW_RESIZABLE: @@ -900,6 +909,14 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value) } else if (attrib == GLFW_FOCUS_ON_SHOW) window->focusOnShow = value; + else if (attrib == GLFW_MOUSE_PASSTHROUGH) + { + if (window->mousePassthrough == value) + return; + + window->mousePassthrough = value; + _glfwPlatformSetWindowMousePassthrough(window, value); + } else _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); } @@ -1102,3 +1119,4 @@ GLFWAPI void glfwPostEmptyEvent(void) _GLFW_REQUIRE_INIT(); _glfwPlatformPostEmptyEvent(); } + diff --git a/src/wl_init.c b/src/wl_init.c index 558ff8a8..21a808aa 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -341,9 +341,9 @@ static void pointerHandleAxis(void* data, axis == WL_POINTER_AXIS_VERTICAL_SCROLL); if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) - x = wl_fixed_to_double(value) * scrollFactor; + x = -wl_fixed_to_double(value) * scrollFactor; else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) - y = wl_fixed_to_double(value) * scrollFactor; + y = -wl_fixed_to_double(value) * scrollFactor; _glfwInputScroll(window, x, y); } @@ -1146,11 +1146,6 @@ int _glfwPlatformInit(void) // Sync so we got all initial output events wl_display_roundtrip(_glfw.wl.display); -#ifdef __linux__ - if (!_glfwInitJoysticksLinux()) - return GLFW_FALSE; -#endif - _glfwInitTimerPOSIX(); _glfw.wl.timerfd = -1; @@ -1213,9 +1208,6 @@ int _glfwPlatformInit(void) void _glfwPlatformTerminate(void) { -#ifdef __linux__ - _glfwTerminateJoysticksLinux(); -#endif _glfwTerminateEGL(); if (_glfw.wl.egl.handle) { diff --git a/src/wl_window.c b/src/wl_window.c index a9cefc97..2e0d18a7 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -955,8 +955,10 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) { _glfwPlatformGetWindowSize(window, width, height); - *width *= window->wl.scale; - *height *= window->wl.scale; + if (width) + *width *= window->wl.scale; + if (height) + *height *= window->wl.scale; } void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, @@ -1127,6 +1129,19 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) "Wayland: Window attribute setting not implemented yet"); } +void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled) +{ + if (enabled) + { + struct wl_region* region = wl_compositor_create_region(_glfw.wl.compositor); + wl_surface_set_input_region(window->wl.surface, region); + wl_region_destroy(region); + } + else + wl_surface_set_input_region(window->wl.surface, 0); + wl_surface_commit(window->wl.surface); +} + float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) { return 1.f; diff --git a/src/x11_init.c b/src/x11_init.c index 80b9bb42..dd24f112 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -851,6 +851,35 @@ static GLFWbool initExtensions(void) } } +#if defined(__CYGWIN__) + _glfw.x11.xshape.handle = _glfw_dlopen("libXext-6.so"); +#else + _glfw.x11.xshape.handle = _glfw_dlopen("libXext.so.6"); +#endif + if (_glfw.x11.xshape.handle) + { + _glfw.x11.xshape.QueryExtension = (PFN_XShapeQueryExtension) + _glfw_dlsym(_glfw.x11.xshape.handle, "XShapeQueryExtension"); + _glfw.x11.xshape.ShapeCombineRegion = (PFN_XShapeCombineRegion) + _glfw_dlsym(_glfw.x11.xshape.handle, "XShapeCombineRegion"); + _glfw.x11.xshape.QueryVersion = (PFN_XShapeQueryVersion) + _glfw_dlsym(_glfw.x11.xshape.handle, "XShapeQueryVersion"); + _glfw.x11.xshape.ShapeCombineMask = (PFN_XShapeCombineMask) + _glfw_dlsym(_glfw.x11.xshape.handle, "XShapeCombineMask"); + + if (XShapeQueryExtension(_glfw.x11.display, + &_glfw.x11.xshape.errorBase, + &_glfw.x11.xshape.eventBase)) + { + if (XShapeQueryVersion(_glfw.x11.display, + &_glfw.x11.xshape.major, + &_glfw.x11.xshape.minor)) + { + _glfw.x11.xshape.available = GLFW_TRUE; + } + } + } + // Update the key code LUT // FIXME: We should listen to XkbMapNotify events to track changes to // the keyboard mapping. @@ -1122,6 +1151,8 @@ int _glfwPlatformInit(void) _glfw_dlsym(_glfw.x11.xlib.handle, "XCreateFontCursor"); _glfw.x11.xlib.CreateIC = (PFN_XCreateIC) _glfw_dlsym(_glfw.x11.xlib.handle, "XCreateIC"); + _glfw.x11.xlib.CreateRegion = (PFN_XCreateRegion) + _glfw_dlsym(_glfw.x11.xlib.handle, "XCreateRegion"); _glfw.x11.xlib.CreateWindow = (PFN_XCreateWindow) _glfw_dlsym(_glfw.x11.xlib.handle, "XCreateWindow"); _glfw.x11.xlib.DefineCursor = (PFN_XDefineCursor) @@ -1132,6 +1163,8 @@ int _glfwPlatformInit(void) _glfw_dlsym(_glfw.x11.xlib.handle, "XDeleteProperty"); _glfw.x11.xlib.DestroyIC = (PFN_XDestroyIC) _glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyIC"); + _glfw.x11.xlib.DestroyRegion = (PFN_XDestroyRegion) + _glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyRegion"); _glfw.x11.xlib.DestroyWindow = (PFN_XDestroyWindow) _glfw_dlsym(_glfw.x11.xlib.handle, "XDestroyWindow"); _glfw.x11.xlib.DisplayKeycodes = (PFN_XDisplayKeycodes) @@ -1344,11 +1377,6 @@ int _glfwPlatformInit(void) NULL); } -#if defined(__linux__) - if (!_glfwInitJoysticksLinux()) - return GLFW_FALSE; -#endif - _glfwInitTimerPOSIX(); _glfwPollMonitorsX11(); @@ -1442,10 +1470,6 @@ void _glfwPlatformTerminate(void) _glfwTerminateEGL(); _glfwTerminateGLX(); -#if defined(__linux__) - _glfwTerminateJoysticksLinux(); -#endif - if (_glfw.x11.xlib.handle) { _glfw_dlclose(_glfw.x11.xlib.handle); diff --git a/src/x11_platform.h b/src/x11_platform.h index f55d9d1c..c5137bc3 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -48,6 +48,9 @@ // The XInput extension provides raw mouse motion input #include +// The Shape extension provides custom window shapes +#include + typedef XClassHint* (* PFN_XAllocClassHint)(void); typedef XSizeHints* (* PFN_XAllocSizeHints)(void); typedef XWMHints* (* PFN_XAllocWMHints)(void); @@ -61,11 +64,13 @@ typedef int (* PFN_XConvertSelection)(Display*,Atom,Atom,Atom,Window,Time); typedef Colormap (* PFN_XCreateColormap)(Display*,Window,Visual*,int); typedef Cursor (* PFN_XCreateFontCursor)(Display*,unsigned int); typedef XIC (* PFN_XCreateIC)(XIM,...); +typedef Region (* PFN_XCreateRegion)(void); typedef Window (* PFN_XCreateWindow)(Display*,Window,int,int,unsigned int,unsigned int,unsigned int,int,unsigned int,Visual*,unsigned long,XSetWindowAttributes*); typedef int (* PFN_XDefineCursor)(Display*,Window,Cursor); typedef int (* PFN_XDeleteContext)(Display*,XID,XContext); typedef int (* PFN_XDeleteProperty)(Display*,Window,Atom); typedef void (* PFN_XDestroyIC)(XIC); +typedef int (* PFN_XDestroyRegion)(Region); typedef int (* PFN_XDestroyWindow)(Display*,Window); typedef int (* PFN_XDisplayKeycodes)(Display*,int*,int*); typedef int (* PFN_XEventsQueued)(Display*,int); @@ -161,11 +166,13 @@ typedef void (* PFN_Xutf8SetWMProperties)(Display*,Window,const char*,const char #define XCreateColormap _glfw.x11.xlib.CreateColormap #define XCreateFontCursor _glfw.x11.xlib.CreateFontCursor #define XCreateIC _glfw.x11.xlib.CreateIC +#define XCreateRegion _glfw.x11.xlib.CreateRegion #define XCreateWindow _glfw.x11.xlib.CreateWindow #define XDefineCursor _glfw.x11.xlib.DefineCursor #define XDeleteContext _glfw.x11.xlib.DeleteContext #define XDeleteProperty _glfw.x11.xlib.DeleteProperty #define XDestroyIC _glfw.x11.xlib.DestroyIC +#define XDestroyRegion _glfw.x11.xlib.DestroyRegion #define XDestroyWindow _glfw.x11.xlib.DestroyWindow #define XDisplayKeycodes _glfw.x11.xlib.DisplayKeycodes #define XEventsQueued _glfw.x11.xlib.EventsQueued @@ -331,6 +338,16 @@ typedef XRenderPictFormat* (* PFN_XRenderFindVisualFormat)(Display*,Visual const #define XRenderQueryVersion _glfw.x11.xrender.QueryVersion #define XRenderFindVisualFormat _glfw.x11.xrender.FindVisualFormat +typedef Bool (* PFN_XShapeQueryExtension)(Display*,int*,int*); +typedef Status (* PFN_XShapeQueryVersion)(Display*dpy,int*,int*); +typedef void (* PFN_XShapeCombineRegion)(Display*,Window,int,int,int,Region,int); +typedef void (* PFN_XShapeCombineMask)(Display*,Window,int,int,int,Pixmap,int); + +#define XShapeQueryExtension _glfw.x11.xshape.QueryExtension +#define XShapeQueryVersion _glfw.x11.xshape.QueryVersion +#define XShapeCombineRegion _glfw.x11.xshape.ShapeCombineRegion +#define XShapeCombineMask _glfw.x11.xshape.ShapeCombineMask + typedef VkFlags VkXlibSurfaceCreateFlagsKHR; typedef VkFlags VkXcbSurfaceCreateFlagsKHR; @@ -515,11 +532,13 @@ typedef struct _GLFWlibraryX11 PFN_XCreateColormap CreateColormap; PFN_XCreateFontCursor CreateFontCursor; PFN_XCreateIC CreateIC; + PFN_XCreateRegion CreateRegion; PFN_XCreateWindow CreateWindow; PFN_XDefineCursor DefineCursor; PFN_XDeleteContext DeleteContext; PFN_XDeleteProperty DeleteProperty; PFN_XDestroyIC DestroyIC; + PFN_XDestroyRegion DestroyRegion; PFN_XDestroyWindow DestroyWindow; PFN_XDisplayKeycodes DisplayKeycodes; PFN_XEventsQueued EventsQueued; @@ -720,6 +739,19 @@ typedef struct _GLFWlibraryX11 PFN_XRenderFindVisualFormat FindVisualFormat; } xrender; + struct { + GLFWbool available; + void* handle; + int major; + int minor; + int eventBase; + int errorBase; + PFN_XShapeQueryExtension QueryExtension; + PFN_XShapeCombineRegion ShapeCombineRegion; + PFN_XShapeQueryVersion QueryVersion; + PFN_XShapeCombineMask ShapeCombineMask; + } xshape; + } _GLFWlibraryX11; // X11-specific per-monitor data diff --git a/src/x11_window.c b/src/x11_window.c index 8704126e..f7455785 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2702,6 +2702,25 @@ void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled) XFlush(_glfw.x11.display); } +void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enabled) +{ + if (!_glfw.x11.xshape.available) + return; + + if (enabled) + { + Region region = XCreateRegion(); + XShapeCombineRegion(_glfw.x11.display, window->x11.handle, + ShapeInput, 0, 0, region, ShapeSet); + XDestroyRegion(region); + } + else + { + XShapeCombineMask(_glfw.x11.display, window->x11.handle, + ShapeInput, 0, 0, None, ShapeSet); + } +} + float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) { float opacity = 1.f; @@ -2757,7 +2776,8 @@ void _glfwPlatformPollEvents(void) _GLFWwindow* window; #if defined(__linux__) - _glfwDetectJoystickConnectionLinux(); + if (_glfw.joysticksInitialized) + _glfwDetectJoystickConnectionLinux(); #endif XPending(_glfw.x11.display); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index d79e5b87..10125e14 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -35,13 +35,12 @@ add_executable(gamma WIN32 MACOSX_BUNDLE gamma.c ${GLAD_GL}) add_executable(icon WIN32 MACOSX_BUNDLE icon.c ${GLAD_GL}) add_executable(inputlag WIN32 MACOSX_BUNDLE inputlag.c ${GETOPT} ${GLAD_GL}) add_executable(joysticks WIN32 MACOSX_BUNDLE joysticks.c ${GLAD_GL}) -add_executable(opacity WIN32 MACOSX_BUNDLE opacity.c ${GLAD_GL}) add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c ${GLAD_GL}) add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD} ${GLAD_GL}) add_executable(timeout WIN32 MACOSX_BUNDLE timeout.c ${GLAD_GL}) add_executable(title WIN32 MACOSX_BUNDLE title.c ${GLAD_GL}) add_executable(triangle-vulkan WIN32 triangle-vulkan.c ${GLAD_VULKAN}) -add_executable(windows WIN32 MACOSX_BUNDLE windows.c ${GLAD_GL}) +add_executable(window WIN32 MACOSX_BUNDLE window.c ${GLAD_GL}) target_link_libraries(empty Threads::Threads) target_link_libraries(threads Threads::Threads) @@ -50,8 +49,8 @@ if (RT_LIBRARY) target_link_libraries(threads "${RT_LIBRARY}") endif() -set(GUI_ONLY_BINARIES empty gamma icon inputlag joysticks opacity tearing - threads timeout title triangle-vulkan windows) +set(GUI_ONLY_BINARIES empty gamma icon inputlag joysticks tearing threads + timeout title triangle-vulkan window) set(CONSOLE_BINARIES clipboard events msaa glfwinfo iconify monitors reopen cursor usercontext) @@ -70,12 +69,11 @@ if (APPLE) set_target_properties(gamma PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gamma") set_target_properties(inputlag PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Input Lag") set_target_properties(joysticks PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Joysticks") - set_target_properties(opacity PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Opacity") set_target_properties(tearing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Tearing") set_target_properties(threads PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Threads") set_target_properties(timeout PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Timeout") set_target_properties(title PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Title") - set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows") + set_target_properties(window PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Window") set_target_properties(${GUI_ONLY_BINARIES} PROPERTIES MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION} diff --git a/tests/opacity.c b/tests/opacity.c deleted file mode 100644 index e1da9ef1..00000000 --- a/tests/opacity.c +++ /dev/null @@ -1,109 +0,0 @@ -//======================================================================== -// Window opacity test program -// Copyright (c) Camilla Löwy -// -// 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 -#define GLFW_INCLUDE_NONE -#include - -#define NK_IMPLEMENTATION -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_FONT_BAKING -#define NK_INCLUDE_DEFAULT_FONT -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT -#define NK_INCLUDE_STANDARD_VARARGS -#include - -#define NK_GLFW_GL2_IMPLEMENTATION -#include - -#include -#include - -static void error_callback(int error, const char* description) -{ - fprintf(stderr, "Error: %s\n", description); -} - -int main(int argc, char** argv) -{ - GLFWwindow* window; - struct nk_context* nk; - struct nk_font_atlas* atlas; - - glfwSetErrorCallback(error_callback); - - if (!glfwInit()) - exit(EXIT_FAILURE); - - glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); - glfwWindowHint(GLFW_WIN32_KEYBOARD_MENU, GLFW_TRUE); - - window = glfwCreateWindow(400, 400, "Opacity", NULL, NULL); - if (!window) - { - glfwTerminate(); - exit(EXIT_FAILURE); - } - - glfwMakeContextCurrent(window); - gladLoadGL(glfwGetProcAddress); - glfwSwapInterval(1); - - nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS); - nk_glfw3_font_stash_begin(&atlas); - nk_glfw3_font_stash_end(); - - while (!glfwWindowShouldClose(window)) - { - int width, height; - struct nk_rect area; - - glfwGetWindowSize(window, &width, &height); - area = nk_rect(0.f, 0.f, (float) width, (float) height); - - glClear(GL_COLOR_BUFFER_BIT); - nk_glfw3_new_frame(); - if (nk_begin(nk, "", area, 0)) - { - float opacity = glfwGetWindowOpacity(window); - nk_layout_row_dynamic(nk, 30, 2); - if (nk_slider_float(nk, 0.f, &opacity, 1.f, 0.001f)) - glfwSetWindowOpacity(window, opacity); - nk_labelf(nk, NK_TEXT_LEFT, "%0.3f", opacity); - } - - nk_end(nk); - nk_glfw3_render(NK_ANTI_ALIASING_ON); - - glfwSwapBuffers(window); - glfwWaitEventsTimeout(1.0); - } - - nk_glfw3_shutdown(); - glfwTerminate(); - exit(EXIT_SUCCESS); -} - diff --git a/tests/window.c b/tests/window.c new file mode 100644 index 00000000..f427fcad --- /dev/null +++ b/tests/window.c @@ -0,0 +1,417 @@ +//======================================================================== +// Window properties test +// Copyright (c) Camilla Löwy +// +// 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 +#define GLFW_INCLUDE_NONE +#include + +#include + +#define NK_IMPLEMENTATION +#define NK_INCLUDE_FIXED_TYPES +#define NK_INCLUDE_FONT_BAKING +#define NK_INCLUDE_DEFAULT_FONT +#define NK_INCLUDE_DEFAULT_ALLOCATOR +#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT +#define NK_INCLUDE_STANDARD_VARARGS +#define NK_BUTTON_TRIGGER_ON_RELEASE +#include + +#define NK_GLFW_GL2_IMPLEMENTATION +#include + +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + int windowed_x, windowed_y, windowed_width, windowed_height; + int last_xpos = INT_MIN, last_ypos = INT_MIN; + int last_width = INT_MIN, last_height = INT_MIN; + int limit_aspect_ratio = false, aspect_numer = 1, aspect_denom = 1; + int limit_min_size = false, min_width = 400, min_height = 400; + int limit_max_size = false, max_width = 400, max_height = 400; + char width_buffer[10] = "", height_buffer[10] = ""; + char xpos_buffer[10] = "", ypos_buffer[10] = ""; + char numer_buffer[10] = "", denom_buffer[10] = ""; + char min_width_buffer[10] = "", min_height_buffer[10] = ""; + char max_width_buffer[10] = "", max_height_buffer[10] = ""; + int may_close = true; + + if (!glfwInit()) + exit(EXIT_FAILURE); + + glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE); + glfwWindowHint(GLFW_WIN32_KEYBOARD_MENU, GLFW_TRUE); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + + GLFWwindow* window = glfwCreateWindow(600, 600, "Window Features", NULL, NULL); + if (!window) + { + glfwTerminate(); + exit(EXIT_FAILURE); + } + + glfwMakeContextCurrent(window); + gladLoadGL(glfwGetProcAddress); + glfwSwapInterval(0); + + bool position_supported = true; + + glfwGetError(NULL); + glfwGetWindowPos(window, &last_xpos, &last_ypos); + sprintf(xpos_buffer, "%i", last_xpos); + sprintf(ypos_buffer, "%i", last_ypos); + if (glfwGetError(NULL) == GLFW_FEATURE_UNAVAILABLE) + position_supported = false; + + glfwGetWindowSize(window, &last_width, &last_height); + sprintf(width_buffer, "%i", last_width); + sprintf(height_buffer, "%i", last_height); + + sprintf(numer_buffer, "%i", aspect_numer); + sprintf(denom_buffer, "%i", aspect_denom); + + sprintf(min_width_buffer, "%i", min_width); + sprintf(min_height_buffer, "%i", min_height); + sprintf(max_width_buffer, "%i", max_width); + sprintf(max_height_buffer, "%i", max_height); + + struct nk_context* nk = nk_glfw3_init(window, NK_GLFW3_INSTALL_CALLBACKS); + + struct nk_font_atlas* atlas; + nk_glfw3_font_stash_begin(&atlas); + nk_glfw3_font_stash_end(); + + while (!(may_close && glfwWindowShouldClose(window))) + { + int width, height; + + glfwGetWindowSize(window, &width, &height); + + struct nk_rect area = nk_rect(0.f, 0.f, (float) width, (float) height); + nk_window_set_bounds(nk, "main", area); + + nk_glfw3_new_frame(); + if (nk_begin(nk, "main", area, 0)) + { + nk_layout_row_dynamic(nk, 30, 4); + + if (nk_button_label(nk, "Toggle Fullscreen")) + { + if (glfwGetWindowMonitor(window)) + { + glfwSetWindowMonitor(window, NULL, + windowed_x, windowed_y, + windowed_width, windowed_height, 0); + } + else + { + GLFWmonitor* monitor = glfwGetPrimaryMonitor(); + const GLFWvidmode* mode = glfwGetVideoMode(monitor); + glfwGetWindowPos(window, &windowed_x, &windowed_y); + glfwGetWindowSize(window, &windowed_width, &windowed_height); + glfwSetWindowMonitor(window, monitor, + 0, 0, mode->width, mode->height, + mode->refreshRate); + } + } + + if (nk_button_label(nk, "Maximize")) + glfwMaximizeWindow(window); + if (nk_button_label(nk, "Iconify")) + glfwIconifyWindow(window); + if (nk_button_label(nk, "Restore")) + glfwRestoreWindow(window); + + nk_layout_row_dynamic(nk, 30, 1); + + if (glfwGetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH)) + { + nk_label(nk, "Press H to disable mouse passthrough", NK_TEXT_CENTERED); + + if (glfwGetKey(window, GLFW_KEY_H)) + glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, false); + } + + nk_label(nk, "Press Enter in a text field to set value", NK_TEXT_CENTERED); + + nk_flags events; + const nk_flags flags = NK_EDIT_FIELD | + NK_EDIT_SIG_ENTER | + NK_EDIT_GOTO_END_ON_ACTIVATE; + + if (position_supported) + { + int xpos, ypos; + glfwGetWindowPos(window, &xpos, &ypos); + + nk_layout_row_dynamic(nk, 30, 3); + nk_label(nk, "Position", NK_TEXT_LEFT); + + events = nk_edit_string_zero_terminated(nk, flags, xpos_buffer, + sizeof(xpos_buffer), + nk_filter_decimal); + if (events & NK_EDIT_COMMITED) + { + xpos = atoi(xpos_buffer); + glfwSetWindowPos(window, xpos, ypos); + } + else if (xpos != last_xpos || (events & NK_EDIT_DEACTIVATED)) + sprintf(xpos_buffer, "%i", xpos); + + events = nk_edit_string_zero_terminated(nk, flags, ypos_buffer, + sizeof(ypos_buffer), + nk_filter_decimal); + if (events & NK_EDIT_COMMITED) + { + ypos = atoi(ypos_buffer); + glfwSetWindowPos(window, xpos, ypos); + } + else if (ypos != last_ypos || (events & NK_EDIT_DEACTIVATED)) + sprintf(ypos_buffer, "%i", ypos); + + last_xpos = xpos; + last_ypos = ypos; + } + else + nk_label(nk, "Position not supported", NK_TEXT_LEFT); + + nk_layout_row_dynamic(nk, 30, 3); + nk_label(nk, "Size", NK_TEXT_LEFT); + + events = nk_edit_string_zero_terminated(nk, flags, width_buffer, + sizeof(width_buffer), + nk_filter_decimal); + if (events & NK_EDIT_COMMITED) + { + width = atoi(width_buffer); + glfwSetWindowSize(window, width, height); + } + else if (width != last_width || (events & NK_EDIT_DEACTIVATED)) + sprintf(width_buffer, "%i", width); + + events = nk_edit_string_zero_terminated(nk, flags, height_buffer, + sizeof(height_buffer), + nk_filter_decimal); + if (events & NK_EDIT_COMMITED) + { + height = atoi(height_buffer); + glfwSetWindowSize(window, width, height); + } + else if (height != last_height || (events & NK_EDIT_DEACTIVATED)) + sprintf(height_buffer, "%i", height); + + last_width = width; + last_height = height; + + bool update_ratio_limit = false; + if (nk_checkbox_label(nk, "Aspect Ratio", &limit_aspect_ratio)) + update_ratio_limit = true; + + events = nk_edit_string_zero_terminated(nk, flags, numer_buffer, + sizeof(numer_buffer), + nk_filter_decimal); + if (events & NK_EDIT_COMMITED) + { + aspect_numer = abs(atoi(numer_buffer)); + update_ratio_limit = true; + } + else if (events & NK_EDIT_DEACTIVATED) + sprintf(numer_buffer, "%i", aspect_numer); + + events = nk_edit_string_zero_terminated(nk, flags, denom_buffer, + sizeof(denom_buffer), + nk_filter_decimal); + if (events & NK_EDIT_COMMITED) + { + aspect_denom = abs(atoi(denom_buffer)); + update_ratio_limit = true; + } + else if (events & NK_EDIT_DEACTIVATED) + sprintf(denom_buffer, "%i", aspect_denom); + + if (update_ratio_limit) + { + if (limit_aspect_ratio) + glfwSetWindowAspectRatio(window, aspect_numer, aspect_denom); + else + glfwSetWindowAspectRatio(window, GLFW_DONT_CARE, GLFW_DONT_CARE); + } + + bool update_size_limit = false; + + if (nk_checkbox_label(nk, "Minimum Size", &limit_min_size)) + update_size_limit = true; + + events = nk_edit_string_zero_terminated(nk, flags, min_width_buffer, + sizeof(min_width_buffer), + nk_filter_decimal); + if (events & NK_EDIT_COMMITED) + { + min_width = abs(atoi(min_width_buffer)); + update_size_limit = true; + } + else if (events & NK_EDIT_DEACTIVATED) + sprintf(min_width_buffer, "%i", min_width); + + events = nk_edit_string_zero_terminated(nk, flags, min_height_buffer, + sizeof(min_height_buffer), + nk_filter_decimal); + if (events & NK_EDIT_COMMITED) + { + min_height = abs(atoi(min_height_buffer)); + update_size_limit = true; + } + else if (events & NK_EDIT_DEACTIVATED) + sprintf(min_height_buffer, "%i", min_height); + + if (nk_checkbox_label(nk, "Maximum Size", &limit_max_size)) + update_size_limit = true; + + events = nk_edit_string_zero_terminated(nk, flags, max_width_buffer, + sizeof(max_width_buffer), + nk_filter_decimal); + if (events & NK_EDIT_COMMITED) + { + max_width = abs(atoi(max_width_buffer)); + update_size_limit = true; + } + else if (events & NK_EDIT_DEACTIVATED) + sprintf(max_width_buffer, "%i", max_width); + + events = nk_edit_string_zero_terminated(nk, flags, max_height_buffer, + sizeof(max_height_buffer), + nk_filter_decimal); + if (events & NK_EDIT_COMMITED) + { + max_height = abs(atoi(max_height_buffer)); + update_size_limit = true; + } + else if (events & NK_EDIT_DEACTIVATED) + sprintf(max_height_buffer, "%i", max_height); + + if (update_size_limit) + { + glfwSetWindowSizeLimits(window, + limit_min_size ? min_width : GLFW_DONT_CARE, + limit_min_size ? min_height : GLFW_DONT_CARE, + limit_max_size ? max_width : GLFW_DONT_CARE, + limit_max_size ? max_height : GLFW_DONT_CARE); + } + + int fb_width, fb_height; + glfwGetFramebufferSize(window, &fb_width, &fb_height); + nk_label(nk, "Framebuffer Size", NK_TEXT_LEFT); + nk_labelf(nk, NK_TEXT_LEFT, "%i", fb_width); + nk_labelf(nk, NK_TEXT_LEFT, "%i", fb_height); + + float xscale, yscale; + glfwGetWindowContentScale(window, &xscale, &yscale); + nk_label(nk, "Content Scale", NK_TEXT_LEFT); + nk_labelf(nk, NK_TEXT_LEFT, "%f", xscale); + nk_labelf(nk, NK_TEXT_LEFT, "%f", yscale); + + nk_layout_row_begin(nk, NK_DYNAMIC, 30, 5); + int frame_left, frame_top, frame_right, frame_bottom; + glfwGetWindowFrameSize(window, &frame_left, &frame_top, &frame_right, &frame_bottom); + nk_layout_row_push(nk, 1.f / 3.f); + nk_label(nk, "Frame Size:", NK_TEXT_LEFT); + nk_layout_row_push(nk, 1.f / 6.f); + nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_left); + nk_layout_row_push(nk, 1.f / 6.f); + nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_top); + nk_layout_row_push(nk, 1.f / 6.f); + nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_right); + nk_layout_row_push(nk, 1.f / 6.f); + nk_labelf(nk, NK_TEXT_LEFT, "%i", frame_bottom); + nk_layout_row_end(nk); + + nk_layout_row_begin(nk, NK_DYNAMIC, 30, 2); + float opacity = glfwGetWindowOpacity(window); + nk_layout_row_push(nk, 1.f / 3.f); + nk_labelf(nk, NK_TEXT_LEFT, "Opacity: %0.3f", opacity); + nk_layout_row_push(nk, 2.f / 3.f); + if (nk_slider_float(nk, 0.f, &opacity, 1.f, 0.001f)) + glfwSetWindowOpacity(window, opacity); + nk_layout_row_end(nk); + + nk_layout_row_begin(nk, NK_DYNAMIC, 30, 2); + int should_close = glfwWindowShouldClose(window); + nk_layout_row_push(nk, 1.f / 3.f); + if (nk_checkbox_label(nk, "Should Close", &should_close)) + glfwSetWindowShouldClose(window, should_close); + nk_layout_row_push(nk, 2.f / 3.f); + nk_checkbox_label(nk, "May Close", &may_close); + nk_layout_row_end(nk); + + nk_layout_row_dynamic(nk, 30, 1); + nk_label(nk, "Attributes", NK_TEXT_CENTERED); + + nk_layout_row_dynamic(nk, 30, width > 200 ? width / 200 : 1); + + int decorated = glfwGetWindowAttrib(window, GLFW_DECORATED); + if (nk_checkbox_label(nk, "Decorated", &decorated)) + glfwSetWindowAttrib(window, GLFW_DECORATED, decorated); + + int resizable = glfwGetWindowAttrib(window, GLFW_RESIZABLE); + if (nk_checkbox_label(nk, "Resizable", &resizable)) + glfwSetWindowAttrib(window, GLFW_RESIZABLE, resizable); + + int floating = glfwGetWindowAttrib(window, GLFW_FLOATING); + if (nk_checkbox_label(nk, "Floating", &floating)) + glfwSetWindowAttrib(window, GLFW_FLOATING, floating); + + int passthrough = glfwGetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH); + if (nk_checkbox_label(nk, "Mouse Passthrough", &passthrough)) + glfwSetWindowAttrib(window, GLFW_MOUSE_PASSTHROUGH, passthrough); + + int auto_iconify = glfwGetWindowAttrib(window, GLFW_AUTO_ICONIFY); + if (nk_checkbox_label(nk, "Auto Iconify", &auto_iconify)) + glfwSetWindowAttrib(window, GLFW_AUTO_ICONIFY, auto_iconify); + + nk_value_bool(nk, "Focused", glfwGetWindowAttrib(window, GLFW_FOCUSED)); + nk_value_bool(nk, "Hovered", glfwGetWindowAttrib(window, GLFW_HOVERED)); + nk_value_bool(nk, "Visible", glfwGetWindowAttrib(window, GLFW_VISIBLE)); + nk_value_bool(nk, "Iconified", glfwGetWindowAttrib(window, GLFW_ICONIFIED)); + nk_value_bool(nk, "Maximized", glfwGetWindowAttrib(window, GLFW_MAXIMIZED)); + } + nk_end(nk); + + glClear(GL_COLOR_BUFFER_BIT); + nk_glfw3_render(NK_ANTI_ALIASING_ON); + glfwSwapBuffers(window); + + glfwWaitEvents(); + } + + nk_glfw3_shutdown(); + glfwTerminate(); + exit(EXIT_SUCCESS); +} +