Skip to content

Commit

Permalink
Added window creation hint to disable native OS title-bar
Browse files Browse the repository at this point in the history
- Disabling title-bar only implemented for win32 window.
  • Loading branch information
Jaytheway committed Sep 28, 2021
1 parent 1a3b9ea commit 6d3052e
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 0 deletions.
59 changes: 59 additions & 0 deletions include/GLFW/glfw3.h
Expand Up @@ -842,6 +842,12 @@ extern "C" {
* [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib).
*/
#define GLFW_FOCUS_ON_SHOW 0x0002000C
/*! @brief Window has titlebar window hint and attribute
*
* Window has titlebar [window hint](@ref GLFW_TITLEBAR_hint) and
* [window attribute](@ref GLFW_TITLEBAR_attrib).
*/
#define GLFW_TITLEBAR 0x0002000D

/*! @brief Framebuffer bit depth hint.
*
Expand Down Expand Up @@ -1291,8 +1297,30 @@ typedef void (* GLFWerrorfun)(int,const char*);
*
* @ingroup window
*/

typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int);

/*! @brief The function pointer type for window titlebar hittest callbacks.
*
* This is the function pointer type for window titelebar hittest callbacks.
* A window titlebar hittest callback function has the following signature:
* @code
* void callback_name(GLFWwindow* window, int xpos, int ypos, int* hit)
* @endcode
*
* @param[in] window The window that was moved.
* @param[in] xpos The x-coordinate of mouse, in screen coordinates.
* @param[in] ypos The y-coordinate of mouse, in screen coordinates.
* @param[out] hit 'true' or '1' if mouse hovering titlebar.
*
* @sa @ref window_pos
* @sa @ref glfwSetTitlebarHitTestCallback
*
* @ingroup window
*/
typedef void (*GLFWtitlebarhittestfun)(GLFWwindow*, int, int, int*);


/*! @brief The function pointer type for window size callbacks.
*
* This is the function pointer type for window size callbacks. A window size
Expand Down Expand Up @@ -3688,6 +3716,37 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
*/
GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindowposfun callback);

/*! @brief Sets the titlebar hittest callback for the specified window.
*
* This function sets the titlebar hittest callback of the specified window,
* which is called when the mouse hoveres the window to ask client if it's
* hovering over custom titlebar area which needs to be handles as a native
* titlebar. The callback is provided with the x and y coordinates of the mouse
* cursor in screen coordinates.
*
* @param[in] window The window whose callback to set.
* @param[in] callback The new callback, or `NULL` to remove the currently set
* callback.
* @return The previously set callback, or `NULL` if no callback was set or the
* library had not been [initialized](@ref intro_init).
*
* @callback_signature
* @code
* void function_name(GLFWwindow* window, int xpos, int ypos, int* hit)
* @endcode
* For more information about the callback parameters, see the
* [function pointer type](@ref GLFWtitlebarhittestfun).
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_pos
*
* @ingroup window
*/
GLFWAPI GLFWtitlebarhittestfun glfwSetTitlebarHitTestCallback(GLFWwindow* window, GLFWtitlebarhittestfun callback);

/*! @brief Sets the size callback for the specified window.
*
* This function sets the size callback of the specified window, which is
Expand Down
5 changes: 5 additions & 0 deletions premake5.lua
Expand Up @@ -64,6 +64,11 @@ project "GLFW"
"_CRT_SECURE_NO_WARNINGS"
}

links
{
"Dwmapi.lib"
}

filter "configurations:Debug"
runtime "Debug"
symbols "on"
Expand Down
7 changes: 7 additions & 0 deletions src/cocoa_window.m
Expand Up @@ -1337,6 +1337,13 @@ void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
} // autoreleasepool
}

void _glfwPlatformSetWindowTitlebar(_GLFWwindow* window, GLFWbool enabled)
{
// TODO
_glfwInputError(GLFW_PLATFORM_ERROR,
"Cocoa: Window attribute setting not implemented yet");
}

void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
@autoreleasepool {
Expand Down
5 changes: 5 additions & 0 deletions src/internal.h
Expand Up @@ -260,6 +260,7 @@ struct _GLFWwndconfig
GLFWbool resizable;
GLFWbool visible;
GLFWbool decorated;
GLFWbool titlebar;
GLFWbool focused;
GLFWbool autoIconify;
GLFWbool floating;
Expand Down Expand Up @@ -373,6 +374,7 @@ struct _GLFWwindow
// Window settings and state
GLFWbool resizable;
GLFWbool decorated;
GLFWbool titlebar;
GLFWbool autoIconify;
GLFWbool floating;
GLFWbool focusOnShow;
Expand Down Expand Up @@ -400,6 +402,7 @@ struct _GLFWwindow

struct {
GLFWwindowposfun pos;
GLFWtitlebarhittestfun tbhittest;
GLFWwindowsizefun size;
GLFWwindowclosefun close;
GLFWwindowrefreshfun refresh;
Expand Down Expand Up @@ -673,6 +676,7 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window);
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window);
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowTitlebar(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity);

Expand Down Expand Up @@ -708,6 +712,7 @@ void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
void _glfwInputTitleBarHitTest(_GLFWwindow* window, int posX, int posY, int* hit);
void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
void _glfwInputWindowContentScale(_GLFWwindow* window,
float xscale, float yscale);
Expand Down
4 changes: 4 additions & 0 deletions src/null_window.c
Expand Up @@ -185,6 +185,10 @@ void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
{
}

void _glfwPlatformSetWindowTitlebar(_GLFWwindow* window, GLFWbool enabled)
{
}

void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
}
Expand Down
115 changes: 115 additions & 0 deletions src/win32_window.c
Expand Up @@ -35,6 +35,7 @@
#include <string.h>
#include <windowsx.h>
#include <shellapi.h>
#include <uxtheme.h>

// Returns the window style for the specified window
//
Expand Down Expand Up @@ -508,6 +509,8 @@ static void releaseMonitor(_GLFWwindow* window)
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
static RECT border_thickness;

_GLFWwindow* window = GetPropW(hWnd, L"GLFW");
if (!window)
{
Expand Down Expand Up @@ -545,6 +548,48 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,

break;
}

case WM_CREATE:
{
if (_glfw.hints.window.titlebar)
break;

//find border thickness
SetRectEmpty(&border_thickness);
if (GetWindowLongPtr(hWnd, GWL_STYLE) & WS_THICKFRAME)
{
AdjustWindowRectEx(&border_thickness, GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_CAPTION, FALSE, NULL);
border_thickness.left *= -1;
border_thickness.top *= -1;
}
else// if (GetWindowLongPtr(hWnd, GWL_STYLE) & WS_BORDER)
{
SetRect(&border_thickness, 4, 4, 4, 4);
}

MARGINS margins = { 0 };
DwmExtendFrameIntoClientArea(hWnd, &margins);
SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);

break;
}

case WM_ACTIVATE:
{
if (_glfw.hints.window.titlebar)
break;

// Extend the frame into the client area.
MARGINS margins = { 0 };
auto hr = DwmExtendFrameIntoClientArea(hWnd, &margins);

if (!SUCCEEDED(hr))
{
// Handle the error.
}

break;
}
}

return DefWindowProcW(hWnd, uMsg, wParam, lParam);
Expand Down Expand Up @@ -951,6 +996,16 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
break;
}

case WM_NCCALCSIZE:
{
if (window->titlebar)
break;

if (lParam)
return 0;

break;
}
case WM_SIZE:
{
const GLFWbool iconified = wParam == SIZE_MINIMIZED;
Expand Down Expand Up @@ -1182,6 +1237,61 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
DragFinish(drop);
return 0;
}

case WM_ACTIVATE:
{
if (window->titlebar)
break;

// Extend the frame into the client area.
MARGINS margins = { 0 };
auto hr = DwmExtendFrameIntoClientArea(hWnd, &margins);

if (!SUCCEEDED(hr))
{
// Handle the error.
}

break;
}
case WM_NCHITTEST:
{
if (window->titlebar)
break;

POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
ScreenToClient(hWnd, &pt);
RECT rc;
GetClientRect(hWnd, &rc);

int titlebarHittest = 0;
_glfwInputTitleBarHitTest(window, pt.x, pt.y, &titlebarHittest);

if (titlebarHittest)
{
return HTCAPTION;
}
else
{
enum { left = 1, top = 2, right = 4, bottom = 8 };
int hit = 0;
if (pt.x < border_thickness.left) hit |= left;
if (pt.x > rc.right - border_thickness.right) hit |= right;
if (pt.y < border_thickness.top) hit |= top;
if (pt.y > rc.bottom - border_thickness.bottom) hit |= bottom;

if (hit & top && hit & left) return HTTOPLEFT;
if (hit & top && hit & right) return HTTOPRIGHT;
if (hit & bottom && hit & left) return HTBOTTOMLEFT;
if (hit & bottom && hit & right) return HTBOTTOMRIGHT;
if (hit & left) return HTLEFT;
if (hit & top) return HTTOP;
if (hit & right) return HTRIGHT;
if (hit & bottom) return HTBOTTOM;

return HTCLIENT;
}
}
}

return DefWindowProcW(hWnd, uMsg, wParam, lParam);
Expand Down Expand Up @@ -1828,6 +1938,11 @@ void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
updateWindowStyles(window);
}

void _glfwPlatformSetWindowTitlebar(_GLFWwindow* window, GLFWbool enabled)
{
updateWindowStyles(window);
}

void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
{
const HWND after = enabled ? HWND_TOPMOST : HWND_NOTOPMOST;
Expand Down
34 changes: 34 additions & 0 deletions src/window.c
Expand Up @@ -86,6 +86,14 @@ void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
window->callbacks.size((GLFWwindow*) window, width, height);
}

// Notifies shared code that mouse hittest needs to be resolved
//
void _glfwInputTitleBarHitTest(_GLFWwindow* window, int posX, int posY, int* hit)
{
if (window->callbacks.tbhittest)
window->callbacks.tbhittest((GLFWwindow*)window, posX, posY, hit);
}

// Notifies shared code that a window has been iconified or restored
//
void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
Expand Down Expand Up @@ -200,6 +208,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->monitor = (_GLFWmonitor*) monitor;
window->resizable = wndconfig.resizable;
window->decorated = wndconfig.decorated;
window->titlebar = wndconfig.titlebar;
window->autoIconify = wndconfig.autoIconify;
window->floating = wndconfig.floating;
window->focusOnShow = wndconfig.focusOnShow;
Expand Down Expand Up @@ -262,6 +271,7 @@ void glfwDefaultWindowHints(void)
_glfw.hints.window.resizable = GLFW_TRUE;
_glfw.hints.window.visible = GLFW_TRUE;
_glfw.hints.window.decorated = GLFW_TRUE;
_glfw.hints.window.titlebar = GLFW_TRUE;
_glfw.hints.window.focused = GLFW_TRUE;
_glfw.hints.window.autoIconify = GLFW_TRUE;
_glfw.hints.window.centerCursor = GLFW_TRUE;
Expand Down Expand Up @@ -345,6 +355,9 @@ GLFWAPI void glfwWindowHint(int hint, int value)
case GLFW_DECORATED:
_glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_TITLEBAR:
_glfw.hints.window.titlebar = value ? GLFW_TRUE : GLFW_FALSE;
return;
case GLFW_FOCUSED:
_glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
return;
Expand Down Expand Up @@ -828,6 +841,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib)
return window->resizable;
case GLFW_DECORATED:
return window->decorated;
case GLFW_TITLEBAR:
return window->titlebar;
case GLFW_FLOATING:
return window->floating;
case GLFW_AUTO_ICONIFY:
Expand Down Expand Up @@ -889,6 +904,15 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
if (!window->monitor)
_glfwPlatformSetWindowDecorated(window, value);
}
else if (attrib == GLFW_TITLEBAR)
{
if (window->titlebar == value)
return;

window->titlebar = value;
if (!window->monitor)
_glfwPlatformSetWindowTitlebar(window, value);
}
else if (attrib == GLFW_FLOATING)
{
if (window->floating == value)
Expand Down Expand Up @@ -981,6 +1005,16 @@ GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle,
return cbfun;
}

GLFWAPI GLFWtitlebarhittestfun glfwSetTitlebarHitTestCallback(GLFWwindow* handle, GLFWtitlebarhittestfun tbhtfun)
{
_GLFWwindow* window = (_GLFWwindow*)handle;
assert(window != NULL);

_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
_GLFW_SWAP_POINTERS(window->callbacks.tbhittest, tbhtfun);
return tbhtfun;
}

GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle,
GLFWwindowsizefun cbfun)
{
Expand Down

0 comments on commit 6d3052e

Please sign in to comment.