Add glfwSetWindowMonitor

This adds the ability to switch between windowed and full screen modes,
move a full screen window between monitors and update its desired
resolution and refresh rate.

Fixes #43.
This commit is contained in:
Camilla Berglund 2016-02-23 12:26:42 +01:00
parent fb8a31ba3f
commit 6570d0c4b7
16 changed files with 764 additions and 318 deletions

View File

@ -77,6 +77,8 @@ does not find Doxygen, the documentation will not be generated.
- Added `glfwVulkanSupported`, `glfwGetRequiredInstanceExtensions`,
`glfwGetInstanceProcAddress`, `glfwGetPhysicalDevicePresentationSupport` and
`glfwCreateWindowSurface` for platform independent Vulkan support
- Added `glfwSetWindowMonitor` for switching between windowed and full screen
modes and updating the monitor and desired video mode of full screen windows
- Added `glfwMaximizeWindow` and `GLFW_MAXIMIZED` for window maximization
- Added `glfwFocusWindow` for giving windows input focus
- Added `glfwSetWindowSizeLimits` and `glfwSetWindowAspectRatio` for setting

View File

@ -95,8 +95,9 @@ a gamma ramp.
@subsection monitor_modes Video modes
GLFW generally does a good job selecting a suitable video mode when you create
a full screen window, but it is sometimes useful to know exactly which video
modes are supported.
a full screen window, change its video mode or or make a windowed one full
screen, but it is sometimes useful to know exactly which video modes are
supported.
Video modes are represented as @ref GLFWvidmode structures. You can get an
array of the video modes supported by a monitor with @ref glfwGetVideoModes.

View File

@ -26,6 +26,13 @@ Vulkan header inclusion can be selected with
[GLFW_INCLUDE_VULKAN](@ref build_macros).
@subsection news_32_setwindowmonitor Window mode switching
GLFW now supports switching between windowed and full screen modes and updating
the monitor and desired resolution and refresh rate of full screen windows with
@ref glfwSetWindowMonitor.
@subsection news_32_maximize Window maxmimization support
GLFW now supports window maximization with @ref glfwMaximizeWindow and the

View File

@ -56,6 +56,10 @@ GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", glfwGetPrimaryMonito
Full screen windows cover the entire display area of a monitor, have no border
or decorations.
Windowed mode windows can be made full screen by setting a monitor with @ref
glfwSetWindowMonitor, and full screen ones can be made windowed by unsetting it
with the same function.
Each field of the @ref GLFWvidmode structure corresponds to a function parameter
or window hint and combine to form the _desired video mode_ for that window.
The supported video mode most closely matching the desired video mode will be
@ -71,9 +75,11 @@ GLFWvidmode.greenBits | `GLFW_GREEN_BITS` hint
GLFWvidmode.blueBits | `GLFW_BLUE_BITS` hint
GLFWvidmode.refreshRate | `GLFW_REFRESH_RATE` hint
Once you have a full screen window, you can change its resolution with @ref
glfwSetWindowSize. The new video mode will be selected and set the same way as
the video mode chosen by @ref glfwCreateWindow.
Once you have a full screen window, you can change its resolution, refresh rate
and monitor with @ref glfwSetWindowMonitor. If you just need change its
resolution you can also call @ref glfwSetWindowSize. In all cases, the new
video mode will be selected the same way as the video mode chosen by @ref
glfwCreateWindow.
By default, the original video mode of the monitor will be restored and the
window iconified if it loses input focus, to allow the user to switch back to
@ -101,6 +107,18 @@ glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
GLFWwindow* window = glfwCreateWindow(mode->width, mode->height, "My Title", monitor, NULL);
@endcode
This also works for windowed mode windows that are made full screen.
@code
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
@endcode
Note that @ref glfwGetVideoMode returns the _current_ video mode of a monitor,
so if you already have a full screen window on that monitor that you want to
make windowed full screen, you need to have saved the desktop resolution before.
@subsection window_destruction Window destruction
@ -423,7 +441,7 @@ glfwSetWindowSize(window, 640, 480);
@endcode
For full screen windows, the specified size becomes the new resolution of the
window's *desired video mode*. The video mode most closely matching the new
window's desired video mode. The video mode most closely matching the new
desired video mode is set immediately. The window is resized to fit the
resolution of the set video mode.
@ -648,8 +666,31 @@ GLFWmonitor* monitor = glfwGetWindowMonitor(window);
This monitor handle is one of those returned by @ref glfwGetMonitors.
For windowed mode windows, this function returns `NULL`. This is the
recommended way to tell full screen windows from windowed mode windows.
For windowed mode windows, this function returns `NULL`. This is how to tell
full screen windows from windowed mode windows.
You can move windows between monitors or between full screen and windowed mode
with @ref glfwSetWindowMonitor. When making a window full screen on the same or
on a different monitor, specify the desired monitor, resolution and refresh
rate. The position arguments are ignored.
@code
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
@endcode
When making the window windowed, specify the desired position and size. The
refresh rate argument is ignored.
@code
glfwSetWindowMonitor(window, NULL, xpos, ypos, width, height, 0);
@endcode
This restores any previous window settings such as whether it is decorated,
floating, resizable, has size or aspect ratio limits, etc.. To restore a window
that was originally windowed to its original size and position, save these
before making it full screen and then pass them in as above.
@subsection window_iconify Window iconification

View File

@ -89,6 +89,7 @@ typedef enum { DRAW_BALL, DRAW_BALL_SHADOW } DRAW_BALL_ENUM;
typedef struct {float x; float y; float z;} vertex_t;
/* Global vars */
int windowed_xpos, windowed_ypos, windowed_width, windowed_height;
int width, height;
GLfloat deg_rot_y = 0.f;
GLfloat deg_rot_y_inc = 2.f;
@ -238,6 +239,26 @@ void key_callback( GLFWwindow* window, int key, int scancode, int action, int mo
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
if (key == GLFW_KEY_ENTER && action == GLFW_PRESS && mods == GLFW_MOD_ALT)
{
if (glfwGetWindowMonitor(window))
{
glfwSetWindowMonitor(window, NULL,
windowed_xpos, windowed_ypos,
windowed_width, windowed_height, 0);
}
else
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
if (monitor)
{
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwGetWindowPos(window, &windowed_xpos, &windowed_ypos);
glfwGetWindowSize(window, &windowed_width, &windowed_height);
glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
}
}
}
}
static void set_ball_pos ( GLfloat x, GLfloat y )

View File

@ -1718,17 +1718,17 @@ GLFWAPI void glfwWindowHint(int hint, int value);
* glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize.
*
* To create a full screen window, you need to specify the monitor the window
* will cover. If no monitor is specified, windowed mode will be used. Unless
* you have a way for the user to choose a specific monitor, it is recommended
* that you pick the primary monitor. For more information on how to query
* connected monitors, see @ref monitor_monitors.
* will cover. If no monitor is specified, the window will be windowed mode.
* Unless you have a way for the user to choose a specific monitor, it is
* recommended that you pick the primary monitor. For more information on how
* to query connected monitors, see @ref monitor_monitors.
*
* For full screen windows, the specified size becomes the resolution of the
* window's _desired video mode_. As long as a full screen window has input
* focus, the supported video mode most closely matching the desired video mode
* is set for the specified monitor. For more information about full screen
* windows, including the creation of so called _windowed full screen_ or
* _borderless full screen_ windows, see @ref window_windowed_full_screen.
* window's _desired video mode_. As long as a full screen window is not
* iconified, the supported video mode most closely matching the desired video
* mode is set for the specified monitor. For more information about full
* screen windows, including the creation of so called _windowed full screen_
* or _borderless full screen_ windows, see @ref window_windowed_full_screen.
*
* By default, newly created windows use the placement recommended by the
* window system. To create the window at a specific position, make it
@ -1736,8 +1736,8 @@ GLFWAPI void glfwWindowHint(int hint, int value);
* hint, set its [position](@ref window_pos) and then [show](@ref window_hide)
* it.
*
* If a full screen window has input focus, the screensaver is prohibited from
* starting.
* As long as at least one full screen window is not iconified, the screensaver
* is prohibited from starting.
*
* Window systems put limits on window sizes. Very large or very small window
* dimensions may be overridden by the window system on creation. Check the
@ -1751,7 +1751,7 @@ GLFWAPI void glfwWindowHint(int hint, int value);
* @param[in] height The desired height, in screen coordinates, of the window.
* This must be greater than zero.
* @param[in] title The initial, UTF-8 encoded window title.
* @param[in] monitor The monitor to use for full screen mode, or `NULL` to use
* @param[in] monitor The monitor to use for full screen mode, or `NULL` for
* windowed mode.
* @param[in] share The window whose context to share resources with, or `NULL`
* to not share resources.
@ -2044,11 +2044,12 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);
/*! @brief Sets the size limits of the specified window.
*
* This function sets the size limits of the client area of the specified
* window. If the window is full screen or not resizable, this function does
* nothing.
* window. If the window is full screen, the size limits only take effect if
* once it is made windowed. If the window is not resizable, this function
* does nothing.
*
* The size limits are applied immediately and may cause the window to be
* resized.
* The size limits are applied immediately to a windowed mode window and may
* cause it to be resized.
*
* @param[in] window The window to set limits for.
* @param[in] minwidth The minimum width, in screen coordinates, of the client
@ -2080,7 +2081,8 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minhe
/*! @brief Sets the aspect ratio of the specified window.
*
* This function sets the required aspect ratio of the client area of the
* specified window. If the window is full screen or not resizable, this
* specified window. If the window is full screen, the aspect ratio only takes
* effect once it is made windowed. If the window is not resizable, this
* function does nothing.
*
* The aspect ratio is specified as a numerator and a denominator and both
@ -2090,8 +2092,8 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minhe
* If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect
* ratio limit is disabled.
*
* The aspect ratio is applied immediately and may cause the window to be
* resized.
* The aspect ratio is applied immediately to a windowed mode window and may
* cause it to be resized.
*
* @param[in] window The window to set limits for.
* @param[in] numer The numerator of the desired aspect ratio, or
@ -2121,17 +2123,22 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
* This function sets the size, in screen coordinates, of the client area of
* the specified window.
*
* For full screen windows, this function selects and switches to the resolution
* closest to the specified size, without affecting the window's context. As
* the context is unaffected, the bit depths of the framebuffer remain
* unchanged.
* For full screen windows, this function updates the resolution of its desired
* video mode and switches to the video mode closest to it, without affecting
* the window's context. As the context is unaffected, the bit depths of the
* framebuffer remain unchanged.
*
* If you wish to update the refresh rate of the desired video mode in addition
* to its resolution, see @ref glfwSetWindowMonitor.
*
* The window manager may put limits on what sizes are allowed. GLFW cannot
* and should not override these limits.
*
* @param[in] window The window to resize.
* @param[in] width The desired width of the specified window.
* @param[in] height The desired height of the specified window.
* @param[in] width The desired width, in screen coordinates, of the window
* client area.
* @param[in] height The desired height, in screen coordinates, of the window
* client area.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
@ -2140,6 +2147,7 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
*
* @sa @ref window_size
* @sa glfwGetWindowSize
* @sa glfwSetWindowMonitor
*
* @since Added in version 1.0.
* @glfw3 Added window handle parameter.
@ -2376,6 +2384,7 @@ GLFWAPI void glfwFocusWindow(GLFWwindow* window);
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_monitor
* @sa glfwSetWindowMonitor
*
* @since Added in version 3.0.
*
@ -2383,6 +2392,54 @@ GLFWAPI void glfwFocusWindow(GLFWwindow* window);
*/
GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
/*! @brief Sets the mode, monitor, video mode and placement of a window.
*
* This function sets the monitor that the window uses for full screen mode or,
* if the monitor is `NULL`, makes it windowed mode.
*
* When setting a monitor, this function updates the width, height and refresh
* rate of the desired video mode and switches to the video mode closest to it.
* The window position is ignored when setting a monitor.
*
* When the monitor is `NULL`, the position, width and height are used to
* place the window client area. The refresh rate is ignored when no monitor
* is specified.
*
* If you only wish to update the resolution of a full screen window or the
* size of a windowed mode window, see @ref glfwSetWindowSize.
*
* When a window transitions from full screen to windowed mode, this function
* restores any previous window settings such as whether it is decorated,
* floating, resizable, has size or aspect ratio limits, etc..
*
* @param[in] window The window whose monitor, size or video mode to set.
* @param[in] monitor The desired monitor, or `NULL` to set windowed mode.
* @param[in] xpos The desired x-coordinate of the upper-left corner of the
* client area.
* @param[in] ypos The desired y-coordinate of the upper-left corner of the
* client area.
* @param[in] width The desired with, in screen coordinates, of the client area
* or video mode.
* @param[in] height The desired height, in screen coordinates, of the client
* area or video mode.
* @param[in] refreshRate The desired refresh rate, in Hz, of the video mode.
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_monitor
* @sa @ref window_full_screen
* @sa glfwGetWindowMonitor
* @sa glfwSetWindowSize
*
* @since Added in version 3.2.
*
* @ingroup window
*/
GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
/*! @brief Returns an attribute of the specified window.
*
* This function returns the value of an attribute of the specified window or

View File

@ -56,6 +56,26 @@ static NSCursor* getStandardCursor(int shape)
return nil;
}
// Returns the style mask corresponding to the window settings
//
static NSUInteger getStyleMask(_GLFWwindow* window)
{
NSUInteger styleMask = 0;
if (window->monitor || !window->decorated)
styleMask |= NSBorderlessWindowMask;
else
{
styleMask |= NSTitledWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask;
if (window->resizable)
styleMask |= NSResizableWindowMask;
}
return styleMask;
}
// Center the cursor in the view of the window
//
static void centerCursor(_GLFWwindow *window)
@ -86,7 +106,6 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
[window->ns.object setFrame:frame display:YES];
_glfwPlatformFocusWindow(window);
_glfwInputMonitorWindowChange(window->monitor, window);
return status;
}
@ -908,19 +927,6 @@ static GLFWbool createWindow(_GLFWwindow* window,
return GLFW_FALSE;
}
unsigned int styleMask = 0;
if (window->monitor || !wndconfig->decorated)
styleMask = NSBorderlessWindowMask;
else
{
styleMask = NSTitledWindowMask | NSClosableWindowMask |
NSMiniaturizableWindowMask;
if (wndconfig->resizable)
styleMask |= NSResizableWindowMask;
}
NSRect contentRect;
if (window->monitor)
@ -938,7 +944,7 @@ static GLFWbool createWindow(_GLFWwindow* window,
window->ns.object = [[GLFWWindow alloc]
initWithContentRect:contentRect
styleMask:styleMask
styleMask:getStyleMask(window)
backing:NSBackingStoreBuffered
defer:NO];
@ -948,15 +954,15 @@ static GLFWbool createWindow(_GLFWwindow* window,
return GLFW_FALSE;
}
if (wndconfig->resizable)
[window->ns.object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
if (window->monitor)
[window->ns.object setLevel:NSMainMenuWindowLevel + 1];
else
{
[window->ns.object center];
if (wndconfig->resizable)
[window->ns.object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
if (wndconfig->floating)
[window->ns.object setLevel:NSFloatingWindowLevel];
@ -1005,6 +1011,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (window->monitor)
{
_glfwPlatformShowWindow(window);
_glfwPlatformFocusWindow(window);
if (!acquireMonitor(window))
return GLFW_FALSE;
}
@ -1076,7 +1083,10 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
if (window->monitor)
acquireMonitor(window);
{
if (window->monitor->window == window)
acquireMonitor(window);
}
else
[window->ns.object setContentSize:NSMakeSize(width, height)];
}
@ -1174,6 +1184,103 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
[window->ns.object makeKeyAndOrderFront:nil];
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
if (window->monitor == monitor)
{
if (monitor)
{
if (monitor->window == window)
acquireMonitor(window);
}
else
{
const NSRect contentRect =
NSMakeRect(xpos, transformY(ypos + height), width, height);
const NSRect frameRect =
[window->ns.object frameRectForContentRect:contentRect
styleMask:getStyleMask(window)];
[window->ns.object setFrame:frameRect display:YES];
}
return;
}
if (window->monitor)
releaseMonitor(window);
_glfwInputWindowMonitorChange(window, monitor);
const NSUInteger styleMask = getStyleMask(window);
[window->ns.object setStyleMask:styleMask];
[window->ns.object makeFirstResponder:window->ns.view];
NSRect contentRect;
if (monitor)
{
GLFWvidmode mode;
_glfwPlatformGetVideoMode(window->monitor, &mode);
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
contentRect = NSMakeRect(xpos, transformY(ypos + mode.height),
mode.width, mode.height);
}
else
{
contentRect = NSMakeRect(xpos, transformY(ypos + height),
width, height);
}
NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect
styleMask:styleMask];
[window->ns.object setFrame:frameRect display:YES];
if (monitor)
{
[window->ns.object setLevel:NSMainMenuWindowLevel + 1];
[window->ns.object setHasShadow:NO];
acquireMonitor(window);
}
else
{
if (window->numer != GLFW_DONT_CARE &&
window->denom != GLFW_DONT_CARE)
{
[window->ns.object setContentAspectRatio:NSMakeSize(window->numer,
window->denom)];
}
if (window->minwidth != GLFW_DONT_CARE &&
window->minheight != GLFW_DONT_CARE)
{
[window->ns.object setContentMinSize:NSMakeSize(window->minwidth,
window->minheight)];
}
if (window->maxwidth != GLFW_DONT_CARE &&
window->maxheight != GLFW_DONT_CARE)
{
[window->ns.object setContentMaxSize:NSMakeSize(window->maxwidth,
window->maxheight)];
}
if (window->floating)
[window->ns.object setLevel:NSFloatingWindowLevel];
else
[window->ns.object setLevel:NSNormalWindowLevel];
[window->ns.object setHasShadow:YES];
}
}
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
return [window->ns.object isKeyWindow];

View File

@ -339,6 +339,10 @@ struct _GLFWwindow
_GLFWmonitor* monitor;
_GLFWcursor* cursor;
int minwidth, minheight;
int maxwidth, maxheight;
int numer, denom;
// Window input state
GLFWbool stickyKeys;
GLFWbool stickyMouseButtons;
@ -694,6 +698,11 @@ void _glfwPlatformHideWindow(_GLFWwindow* window);
*/
void _glfwPlatformFocusWindow(_GLFWwindow* window);
/*! @copydoc glfwSetWindowMonitor
* @ingroup platform
*/
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
/*! @brief Returns whether the window is focused.
* @ingroup platform
*/
@ -856,6 +865,8 @@ void _glfwInputWindowDamage(_GLFWwindow* window);
*/
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor);
/*! @brief Notifies shared code of a physical key event.
* @param[in] window The window that received the event.
* @param[in] key The key that was pressed or released.

View File

@ -508,6 +508,16 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Mir: Unsupported function %s", __PRETTY_FUNCTION__);
}
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
_glfwInputError(GLFW_PLATFORM_ERROR,

View File

@ -126,7 +126,11 @@ void _glfwInputMonitorChange(void)
for (window = _glfw.windowListHead; window; window = window->next)
{
if (window->monitor == monitors[i])
window->monitor = NULL;
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
}
}
if (_glfw.callbacks.monitor)

View File

@ -197,10 +197,6 @@ typedef struct _GLFWwindowWin32
GLFWbool cursorTracked;
GLFWbool iconified;
int minwidth, minheight;
int maxwidth, maxheight;
int numer, denom;
// The last received cursor position, regardless of source
int cursorPosX, cursorPosY;

View File

@ -42,15 +42,20 @@ static DWORD getWindowStyle(const _GLFWwindow* window)
{
DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
if (window->decorated && !window->monitor)
{
style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
if (window->resizable)
style |= WS_MAXIMIZEBOX | WS_SIZEBOX;
}
else
if (window->monitor)
style |= WS_POPUP;
else
{
if (window->decorated)
{
style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
if (window->resizable)
style |= WS_MAXIMIZEBOX | WS_THICKFRAME;
}
else
style |= WS_POPUP;
}
return style;
}
@ -61,8 +66,8 @@ static DWORD getWindowExStyle(const _GLFWwindow* window)
{
DWORD style = WS_EX_APPWINDOW;
if (window->decorated && !window->monitor)
style |= WS_EX_WINDOWEDGE;
if (window->monitor || window->floating)
style |= WS_EX_TOPMOST;
return style;
}
@ -190,8 +195,7 @@ static void getFullWindowSize(DWORD style, DWORD exStyle,
static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
{
int xoff, yoff;
const float ratio = (float) window->win32.numer /
(float) window->win32.denom;
const float ratio = (float) window->numer / (float) window->denom;
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
0, 0, &xoff, &yoff);
@ -342,7 +346,8 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
SetWindowPos(window->win32.handle, HWND_TOPMOST,
xpos, ypos, mode.width, mode.height, SWP_NOCOPYBITS);
xpos, ypos, mode.width, mode.height,
SWP_NOACTIVATE | SWP_NOCOPYBITS);
_glfwInputMonitorWindowChange(window->monitor, window);
return status;
@ -639,8 +644,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_SIZING:
{
if (window->win32.numer == GLFW_DONT_CARE ||
window->win32.denom == GLFW_DONT_CARE)
if (window->numer == GLFW_DONT_CARE ||
window->denom == GLFW_DONT_CARE)
{
break;
}
@ -654,21 +659,24 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
int xoff, yoff;
MINMAXINFO* mmi = (MINMAXINFO*) lParam;
if (window->monitor)
break;
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
0, 0, &xoff, &yoff);
if (window->win32.minwidth != GLFW_DONT_CARE &&
window->win32.minheight != GLFW_DONT_CARE)
if (window->minwidth != GLFW_DONT_CARE &&
window->minheight != GLFW_DONT_CARE)
{
mmi->ptMinTrackSize.x = window->win32.minwidth + xoff;
mmi->ptMinTrackSize.y = window->win32.minheight + yoff;
mmi->ptMinTrackSize.x = window->minwidth + xoff;
mmi->ptMinTrackSize.y = window->minheight + yoff;
}
if (window->win32.maxwidth != GLFW_DONT_CARE &&
window->win32.maxheight != GLFW_DONT_CARE)
if (window->maxwidth != GLFW_DONT_CARE &&
window->maxheight != GLFW_DONT_CARE)
{
mmi->ptMaxTrackSize.x = window->win32.maxwidth + xoff;
mmi->ptMaxTrackSize.y = window->win32.maxheight + yoff;
mmi->ptMaxTrackSize.x = window->maxwidth + xoff;
mmi->ptMaxTrackSize.y = window->maxheight + yoff;
}
return 0;
@ -827,23 +835,8 @@ static int createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig)
WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
}
if (wndconfig->floating && !window->monitor)
{
SetWindowPos(window->win32.handle,
HWND_TOPMOST,
0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}
DragAcceptFiles(window->win32.handle, TRUE);
window->win32.minwidth = GLFW_DONT_CARE;
window->win32.minheight = GLFW_DONT_CARE;
window->win32.maxwidth = GLFW_DONT_CARE;
window->win32.maxheight = GLFW_DONT_CARE;
window->win32.numer = GLFW_DONT_CARE;
window->win32.denom = GLFW_DONT_CARE;
return GLFW_TRUE;
}
@ -976,6 +969,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (window->monitor)
{
_glfwPlatformShowWindow(window);
_glfwPlatformFocusWindow(window);
if (!acquireMonitor(window))
return GLFW_FALSE;
}
@ -1093,15 +1087,17 @@ void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
if (window->monitor)
acquireMonitor(window);
{
if (window->monitor->window == window)
acquireMonitor(window);
}
else
{
int fullWidth, fullHeight;
getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
width, height, &fullWidth, &fullHeight);
RECT rect = { 0, 0, width, height };
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
SetWindowPos(window->win32.handle, HWND_TOP,
0, 0, fullWidth, fullHeight,
0, 0, rect.right - rect.left, rect.bottom - rect.top,
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);
}
}
@ -1112,11 +1108,6 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
{
RECT area;
window->win32.minwidth = minwidth;
window->win32.minheight = minheight;
window->win32.maxwidth = maxwidth;
window->win32.maxheight = maxheight;
if ((minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) &&
(maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE))
{
@ -1134,9 +1125,6 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom
{
RECT area;
window->win32.numer = numer;
window->win32.denom = denom;
if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
return;
@ -1207,6 +1195,92 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
SetFocus(window->win32.handle);
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
if (window->monitor == monitor)
{
if (monitor)
{
if (monitor->window == window)
acquireMonitor(window);
}
else
{
RECT rect = { xpos, ypos, xpos + width, ypos + height };
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
SetWindowPos(window->win32.handle, HWND_TOP,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOZORDER);
}
return;
}
if (window->monitor)
releaseMonitor(window);
_glfwInputWindowMonitorChange(window, monitor);
if (monitor)
{
GLFWvidmode mode;
DWORD style = GetWindowLongPtrW(window->win32.handle, GWL_STYLE);
UINT flags = SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS;
if (window->decorated)
{
style &= ~WS_OVERLAPPEDWINDOW;
style |= getWindowStyle(window);
SetWindowLongPtrW(window->win32.handle, GWL_STYLE, style);
flags |= SWP_FRAMECHANGED;
}
_glfwPlatformGetVideoMode(monitor, &mode);
_glfwPlatformGetMonitorPos(monitor, &xpos, &ypos);
SetWindowPos(window->win32.handle, HWND_TOPMOST,
xpos, ypos, mode.width, mode.height,
flags);
acquireMonitor(window);
}
else
{
HWND after;
RECT rect = { xpos, ypos, xpos + width, ypos + height };
DWORD style = GetWindowLongPtrW(window->win32.handle, GWL_STYLE);
UINT flags = SWP_NOACTIVATE | SWP_NOCOPYBITS;
if (window->decorated)
{
style &= ~WS_POPUP;
style |= getWindowStyle(window);
SetWindowLongPtrW(window->win32.handle, GWL_STYLE, style);
flags |= SWP_FRAMECHANGED;
}
if (window->floating)
after = HWND_TOPMOST;
else
after = HWND_NOTOPMOST;
AdjustWindowRectEx(&rect, getWindowStyle(window),
FALSE, getWindowExStyle(window));
SetWindowPos(window->win32.handle, after,
rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
flags);
}
}
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
return window->win32.handle == GetActiveWindow();

View File

@ -110,6 +110,11 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window)
window->callbacks.close((GLFWwindow*) window);
}
void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor)
{
window->monitor = monitor;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW public API //////
@ -154,13 +159,6 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
}
}
if (monitor)
{
wndconfig.resizable = GLFW_TRUE;
wndconfig.visible = GLFW_TRUE;
wndconfig.focused = GLFW_TRUE;
}
if (!_glfwIsValidContextConfig(&ctxconfig))
return NULL;
@ -182,6 +180,13 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
window->floating = wndconfig.floating;
window->cursorMode = GLFW_CURSOR_NORMAL;
window->minwidth = GLFW_DONT_CARE;
window->minheight = GLFW_DONT_CARE;
window->maxwidth = GLFW_DONT_CARE;
window->maxheight = GLFW_DONT_CARE;
window->numer = GLFW_DONT_CARE;
window->denom = GLFW_DONT_CARE;
// Save the currently current context so it can be restored later
previous = _glfwPlatformGetCurrentContext();
@ -510,11 +515,8 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
_GLFW_REQUIRE_INIT();
if (window->monitor)
{
window->videoMode.width = width;
window->videoMode.height = height;
}
window->videoMode.width = width;
window->videoMode.height = height;
_glfwPlatformSetWindowSize(window, width, height);
}
@ -528,6 +530,11 @@ GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle,
_GLFW_REQUIRE_INIT();
window->minwidth = minwidth;
window->minheight = minheight;
window->maxwidth = maxwidth;
window->maxheight = maxheight;
if (window->monitor || !window->resizable)
return;
@ -543,6 +550,9 @@ GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)
_GLFW_REQUIRE_INIT();
window->numer = numer;
window->denom = denom;
if (window->monitor || !window->resizable)
return;
@ -709,6 +719,27 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
return (GLFWmonitor*) window->monitor;
}
GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
GLFWmonitor* mh,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
_GLFWwindow* window = (_GLFWwindow*) wh;
_GLFWmonitor* monitor = (_GLFWmonitor*) mh;
assert(window);
_GLFW_REQUIRE_INIT();
window->videoMode.width = width;
window->videoMode.height = height;
window->videoMode.refreshRate = refreshRate;
_glfwPlatformSetWindowMonitor(window, monitor,
xpos, ypos, width, height,
refreshRate);
}
GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer)
{
_GLFWwindow* window = (_GLFWwindow*) handle;

View File

@ -489,6 +489,16 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
fprintf(stderr, "_glfwPlatformFocusWindow not implemented yet\n");
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
// TODO
fprintf(stderr, "_glfwPlatformSetWindowMonitor not implemented yet\n");
}
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
// TODO

View File

@ -199,6 +199,145 @@ static void sendEventToWM(_GLFWwindow* window, Atom type,
&event);
}
// Updates the normal hints according to the window settings
//
static void updateNormalHints(_GLFWwindow* window)
{
XSizeHints* hints = XAllocSizeHints();
if (!window->monitor)
{
if (window->resizable)
{
if (window->minwidth != GLFW_DONT_CARE &&
window->minwidth != GLFW_DONT_CARE &&
window->maxwidth != GLFW_DONT_CARE &&
window->maxwidth != GLFW_DONT_CARE)
{
hints->flags |= (PMinSize | PMaxSize);
hints->min_width = window->minwidth;
hints->min_height = window->minheight;
hints->max_width = window->maxwidth;
hints->max_height = window->maxheight;
}
if (window->numer != GLFW_DONT_CARE &&
window->denom != GLFW_DONT_CARE)
{
hints->flags |= PAspect;
hints->min_aspect.x = hints->max_aspect.x = window->numer;
hints->min_aspect.y = hints->max_aspect.y = window->denom;
}
}
else
{
int width, height;
_glfwPlatformGetWindowSize(window, &width, &height);
hints->flags |= (PMinSize | PMaxSize);
hints->min_width = hints->max_width = width;
hints->min_height = hints->max_height = height;
}
}
XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
XFree(hints);
}
// Updates the full screen status of the window
//
static void updateWindowMode(_GLFWwindow* window)
{
updateNormalHints(window);
if (window->monitor)
{
if (_glfw.x11.xinerama.available &&
_glfw.x11.NET_WM_FULLSCREEN_MONITORS)
{
sendEventToWM(window,
_glfw.x11.NET_WM_FULLSCREEN_MONITORS,
window->monitor->x11.index,
window->monitor->x11.index,
window->monitor->x11.index,
window->monitor->x11.index,
0);
}
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
{
sendEventToWM(window,
_glfw.x11.NET_WM_STATE,
_NET_WM_STATE_ADD,
_glfw.x11.NET_WM_STATE_FULLSCREEN,
0, 1, 0);
}
else
{
// This is the butcher's way of removing window decorations
// Setting the override-redirect attribute on a window makes the
// window manager ignore the window completely (ICCCM, section 4)
// The good thing is that this makes undecorated full screen windows
// easy to do; the bad thing is that we have to do everything
// manually and some things (like iconify/restore) won't work at
// all, as those are tasks usually performed by the window manager
XSetWindowAttributes attributes;
attributes.override_redirect = True;
XChangeWindowAttributes(_glfw.x11.display,
window->x11.handle,
CWOverrideRedirect,
&attributes);
window->x11.overrideRedirect = GLFW_TRUE;
}
if (_glfw.x11.NET_WM_BYPASS_COMPOSITOR)
{
const unsigned long value = 1;
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
PropModeReplace, (unsigned char*) &value, 1);
}
}
else
{
if (_glfw.x11.xinerama.available &&
_glfw.x11.NET_WM_FULLSCREEN_MONITORS)
{
XDeleteProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_FULLSCREEN_MONITORS);
}
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
{
sendEventToWM(window,
_glfw.x11.NET_WM_STATE,
_NET_WM_STATE_REMOVE,
_glfw.x11.NET_WM_STATE_FULLSCREEN,
0, 1, 0);
}
else
{
XSetWindowAttributes attributes;
attributes.override_redirect = False;
XChangeWindowAttributes(_glfw.x11.display,
window->x11.handle,
CWOverrideRedirect,
&attributes);
window->x11.overrideRedirect = GLFW_FALSE;
}
if (_glfw.x11.NET_WM_BYPASS_COMPOSITOR)
{
XDeleteProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_BYPASS_COMPOSITOR);
}
}
}
// Splits and translates a text/uri-list into separate file paths
// NOTE: This function destroys the provided string
//
@ -300,84 +439,57 @@ static GLFWbool createWindow(_GLFWwindow* window,
(XPointer) window);
}
if (window->monitor)
if (!wndconfig->decorated)
{
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_FULLSCREEN)
struct
{
// This is the butcher's way of removing window decorations
// Setting the override-redirect attribute on a window makes the
// window manager ignore the window completely (ICCCM, section 4)
// The good thing is that this makes undecorated full screen windows
// easy to do; the bad thing is that we have to do everything
// manually and some things (like iconify/restore) won't work at
// all, as those are tasks usually performed by the window manager
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} hints;
XSetWindowAttributes attributes;
attributes.override_redirect = True;
XChangeWindowAttributes(_glfw.x11.display,
window->x11.handle,
CWOverrideRedirect,
&attributes);
hints.flags = 2; // Set decorations
hints.decorations = 0; // No decorations
window->x11.overrideRedirect = GLFW_TRUE;
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.MOTIF_WM_HINTS,
_glfw.x11.MOTIF_WM_HINTS, 32,
PropModeReplace,
(unsigned char*) &hints,
sizeof(hints) / sizeof(long));
}
if (wndconfig->floating)
{
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_ABOVE)
{
Atom value = _glfw.x11.NET_WM_STATE_ABOVE;
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char*) &value, 1);
}
}
else
{
if (!wndconfig->decorated)
{
struct
{
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} hints;
hints.flags = 2; // Set decorations
hints.decorations = 0; // No decorations
if (wndconfig->maximized && !window->monitor)
{
if (_glfw.x11.NET_WM_STATE &&
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
{
const Atom states[2] =
{
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ
};
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.MOTIF_WM_HINTS,
_glfw.x11.MOTIF_WM_HINTS, 32,
PropModeReplace,
(unsigned char*) &hints,
sizeof(hints) / sizeof(long));
}
if (wndconfig->floating)
{
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_ABOVE)
{
sendEventToWM(window,
_glfw.x11.NET_WM_STATE,
_NET_WM_STATE_ADD,
_glfw.x11.NET_WM_STATE_ABOVE,
0, 1, 0);
}
}
if (wndconfig->maximized)
{
if (_glfw.x11.NET_WM_STATE &&
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
{
const Atom states[2] =
{
_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ
};
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char*) &states, 2);
}
_glfw.x11.NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char*) &states, 2);
}
}
// Declare the WM protocols supported by GLFW
{
int count = 0;
@ -436,27 +548,7 @@ static GLFWbool createWindow(_GLFWwindow* window,
XFree(hints);
}
// Set ICCCM WM_NORMAL_HINTS property (even if no parts are set)
{
XSizeHints* hints = XAllocSizeHints();
hints->flags = 0;
if (window->monitor)
{
hints->flags |= PPosition;
_glfwPlatformGetMonitorPos(window->monitor, &hints->x, &hints->y);
}
if (!wndconfig->resizable)
{
hints->flags |= (PMinSize | PMaxSize);
hints->min_width = hints->max_width = wndconfig->width;
hints->min_height = hints->max_height = wndconfig->height;
}
XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
XFree(hints);
}
updateNormalHints(window);
// Set ICCCM WM_CLASS property
// HACK: Until a mechanism for specifying the application name is added, the
@ -731,24 +823,17 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
DefaultExposures);
}
_glfw.x11.saver.count++;
if (!window->monitor->window)
_glfw.x11.saver.count++;
status = _glfwSetVideoModeX11(window->monitor, &window->videoMode);
if (_glfw.x11.NET_WM_BYPASS_COMPOSITOR)
{
const unsigned long value = 1;
XChangeProperty(_glfw.x11.display, window->x11.handle,
_glfw.x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
PropModeReplace, (unsigned char*) &value, 1);
}
// Position the window over its monitor
if (window->x11.overrideRedirect)
{
int xpos, ypos;
GLFWvidmode mode;
// Manually position the window over its monitor
_glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
_glfwPlatformGetVideoMode(window->monitor, &mode);
@ -756,31 +841,6 @@ static GLFWbool acquireMonitor(_GLFWwindow* window)
xpos, ypos, mode.width, mode.height);
}
if (_glfw.x11.xinerama.available && _glfw.x11.NET_WM_FULLSCREEN_MONITORS)
{
sendEventToWM(window,
_glfw.x11.NET_WM_FULLSCREEN_MONITORS,
window->monitor->x11.index,
window->monitor->x11.index,
window->monitor->x11.index,
window->monitor->x11.index,
0);
}
_glfwPlatformFocusWindow(window);
if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
{
// Ask the window manager to make the GLFW window a full screen window
// Full screen windows are undecorated and, when focused, are kept
// on top of all other windows
sendEventToWM(window,
_glfw.x11.NET_WM_STATE,
_NET_WM_STATE_ADD,
_glfw.x11.NET_WM_STATE_FULLSCREEN,
0, 1, 0);
}
_glfwInputMonitorWindowChange(window->monitor, window);
return status;
}
@ -1124,9 +1184,6 @@ static void processEvent(XEvent *event)
case ConfigureNotify:
{
if (!window->x11.overrideRedirect && !event->xany.send_event)
return;
if (event->xconfigure.width != window->x11.width ||
event->xconfigure.height != window->x11.height)
{
@ -1145,12 +1202,15 @@ static void processEvent(XEvent *event)
if (event->xconfigure.x != window->x11.xpos ||
event->xconfigure.y != window->x11.ypos)
{
_glfwInputWindowPos(window,
event->xconfigure.x,
event->xconfigure.y);
if (window->x11.overrideRedirect || event->xany.send_event)
{
_glfwInputWindowPos(window,
event->xconfigure.x,
event->xconfigure.y);
window->x11.xpos = event->xconfigure.x;
window->x11.ypos = event->xconfigure.y;
window->x11.xpos = event->xconfigure.x;
window->x11.ypos = event->xconfigure.y;
}
}
return;
@ -1459,6 +1519,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (window->monitor)
{
_glfwPlatformShowWindow(window);
updateWindowMode(window);
if (!acquireMonitor(window))
return GLFW_FALSE;
}
@ -1654,31 +1715,13 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
if (window->monitor)
{
_glfwSetVideoModeX11(window->monitor, &window->videoMode);
if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_FULLSCREEN)
{
GLFWvidmode mode;
_glfwPlatformGetVideoMode(window->monitor, &mode);
XResizeWindow(_glfw.x11.display, window->x11.handle,
mode.width, mode.height);
}
if (window->monitor->window == window)
acquireMonitor(window);
}
else
{
if (!window->resizable)
{
// Update window size restrictions to match new window size
XSizeHints* hints = XAllocSizeHints();
hints->flags |= (PMinSize | PMaxSize);
hints->min_width = hints->max_width = width;
hints->min_height = hints->max_height = height;
XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
XFree(hints);
}
updateNormalHints(window);
XResizeWindow(_glfw.x11.display, window->x11.handle, width, height);
}
@ -1690,55 +1733,14 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight)
{
long supplied;
XSizeHints* hints = XAllocSizeHints();
if (XGetWMNormalHints(_glfw.x11.display, window->x11.handle, hints, &supplied))
{
if (minwidth == GLFW_DONT_CARE || minwidth == GLFW_DONT_CARE)
hints->flags &= ~PMinSize;
else
{
hints->flags |= PMinSize;
hints->min_width = minwidth;
hints->min_height = minheight;
}
if (maxwidth == GLFW_DONT_CARE || maxwidth == GLFW_DONT_CARE)
hints->flags &= ~PMaxSize;
else
{
hints->flags |= PMaxSize;
hints->max_width = maxwidth;
hints->max_height = maxheight;
}
XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
}
XFree(hints);
updateNormalHints(window);
XFlush(_glfw.x11.display);
}
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
{
long supplied;
XSizeHints* hints = XAllocSizeHints();
if (XGetWMNormalHints(_glfw.x11.display, window->x11.handle, hints, &supplied))
{
if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
hints->flags &= ~PAspect;
else
{
hints->flags |= PAspect;
hints->min_aspect.x = hints->max_aspect.x = numer;
hints->min_aspect.y = hints->max_aspect.y = denom;
}
XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
}
XFree(hints);
updateNormalHints(window);
XFlush(_glfw.x11.display);
}
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
@ -1907,6 +1909,48 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
XFlush(_glfw.x11.display);
}
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
if (window->monitor == monitor)
{
if (monitor)
{
if (monitor->window == window)
acquireMonitor(window);
}
else
{
XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
xpos, ypos, width, height);
}
return;
}
if (window->monitor)
releaseMonitor(window);
_glfwInputWindowMonitorChange(window, monitor);
updateWindowMode(window);
if (window->monitor)
{
XMapRaised(_glfw.x11.display, window->x11.handle);
acquireMonitor(window);
}
else
{
XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
xpos, ypos, width, height);
}
XFlush(_glfw.x11.display);
}
int _glfwPlatformWindowFocused(_GLFWwindow* window)
{
Window focused;

View File

@ -36,6 +36,8 @@
#include "getopt.h"
static int windowed_xpos, windowed_ypos, windowed_width, windowed_height;
static void usage(void)
{
printf("Usage: iconify [-h] [-f [-a] [-n]]\n");
@ -74,6 +76,34 @@ static void key_callback(GLFWwindow* window, int key, int scancode, int action,
case GLFW_KEY_ESCAPE:
glfwSetWindowShouldClose(window, GLFW_TRUE);
break;
case GLFW_KEY_ENTER:
{
if (mods != GLFW_MOD_ALT)
return;
if (glfwGetWindowMonitor(window))
{
glfwSetWindowMonitor(window, NULL,
windowed_xpos, windowed_ypos,
windowed_width, windowed_height,
0);
}
else
{
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
if (monitor)
{
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
glfwGetWindowPos(window, &windowed_xpos, &windowed_ypos);
glfwGetWindowSize(window, &windowed_width, &windowed_height);
glfwSetWindowMonitor(window, monitor,
0, 0, mode->width, mode->height,
mode->refreshRate);
}
}
break;
}
}
}