From 9359bdc27389711961ecbb089ac9eaf2f35493da Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sun, 18 Jul 2021 21:35:52 -0700 Subject: [PATCH] glfw: add Window.create Signed-off-by: Stephen Gutekanst --- glfw/src/Window.zig | 144 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/glfw/src/Window.zig b/glfw/src/Window.zig index 65df6f72..30a920f2 100644 --- a/glfw/src/Window.zig +++ b/glfw/src/Window.zig @@ -5,9 +5,12 @@ const c = @import("c.zig").c; const Error = @import("errors.zig").Error; const getError = @import("errors.zig").getError; +const Monitor = @import("Monitor.zig"); const Window = @This(); +handle: *c.GLFWwindow, + /// Resets all window hints to their default values. /// /// This function resets all window hints to their default values. @@ -75,6 +78,133 @@ pub fn hintString(hint_const: usize, value: [:0]const u8) Error!void { try getError(); } +/// Creates a window and its associated context. +/// +/// This function creates a window and its associated OpenGL or OpenGL ES context. Most of the +/// options controlling how the window and its context should be created are specified with window +/// hints using `glfw.Window.hint`. +/// +/// Successful creation does not change which context is current. Before you can use the newly +/// created context, you need to make it current using `glfw.Window.makeContextCurrent`. For +/// information about the `share` parameter, see context_sharing. +/// +/// The created window, framebuffer and context may differ from what you requested, as not all +/// parameters and hints are hard constraints. This includes the size of the window, especially for +/// full screen windows. To query the actual attributes of the created window, framebuffer and +/// context, see glfw.Window.getAttrib, glfw.Window.getSize and glfw.window.getFramebufferSize. +/// +/// To create a full screen window, you need to specify the monitor the window 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 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 window_windowed_full_screen. +/// +/// Once you have created the window, you can switch it between windowed and full screen mode with +/// glfw.Window.setMonitor. This will not affect its OpenGL or OpenGL ES context. +/// +/// By default, newly created windows use the placement recommended by the window system. To create +/// the window at a specific position, make it initially invisible using the glfw.version window +/// hint, set its position and then show it. +/// +/// 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 actual size after creation. +/// +/// The swap interval is not set during window creation and the initial value may vary depending on +/// driver settings and defaults. +/// +/// Possible errors include glfw.Error.NotInitialized, glfw.Error.InvalidEnum, glfw.Error.InvalidValue, +/// glfw.Error.APIUnavailable, glfw.Error.VersionUnavailable, glfw.Error.FormatUnavailable and +/// glfw.Error.PlatformError. +/// +/// Parameters are as follows: +/// +/// * `width` The desired width, in screen coordinates, of the window. +/// * `height` The desired height, in screen coordinates, of the window. +/// * `title` The initial, UTF-8 encoded window title. +/// * `monitor` The monitor to use for full screen mode, or `null` for windowed mode. +/// * `share` The window whose context to share resources with, or `null` to not share resources. +/// +/// win32: Window creation will fail if the Microsoft GDI software OpenGL implementation is the +/// only one available. +/// +/// win32: If the executable has an icon resource named `GLFW_ICON`, it will be set as the initial +/// icon for the window. If no such icon is present, the `IDI_APPLICATION` icon will be used +/// instead. To set a different icon, see glfw.Window.setIcon. +/// +/// win32: The context to share resources with must not be current on any other thread. +/// +/// macos: The OS only supports forward-compatible core profile contexts for OpenGL versions 3.2 +/// and later. Before creating an OpenGL context of version 3.2 or later you must set the +/// `glfw.opengl_forward_compat` and `glfw.opengl_profile` hints accordingly. OpenGL 3.0 and 3.1 +/// contexts are not supported at all on macOS. +/// +/// macos: The GLFW window has no icon, as it is not a document window, but the dock icon will be +/// the same as the application bundle's icon. For more information on bundles, see the +/// [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) +/// in the Mac Developer Library. +/// +/// macos: The first time a window is created the menu bar is created. If GLFW finds a `MainMenu.nib` +/// it is loaded and assumed to contain a menu bar. Otherwise a minimal menu bar is created +/// manually with common commands like Hide, Quit and About. The About entry opens a minimal about +/// dialog with information from the application's bundle. Menu bar creation can be disabled +/// entirely with the glfw.cocoa_menubar init hint. +/// +/// macos: On OS X 10.10 and later the window frame will not be rendered at full resolution on +/// Retina displays unless the glfw.cocoa_retina_framebuffer hint is true (1) and the `NSHighResolutionCapable` +/// key is enabled in the application bundle's `Info.plist`. For more information, see +/// [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) +/// in the Mac Developer Library. The GLFW test and example programs use a custom `Info.plist` +/// template for this, which can be found as `CMake/MacOSXBundleInfo.plist.in` in the source tree. +/// +/// macos: When activating frame autosaving with glfw.cocoa_frame_name, the specified window size +/// and position may be overridden by previously saved values. +/// +/// x11: Some window managers will not respect the placement of initially hidden windows. +/// +/// x11: Due to the asynchronous nature of X11, it may take a moment for a window to reach its +/// requested state. This means you may not be able to query the final size, position or other +/// attributes directly after window creation. +/// +/// x11: The class part of the `WM_CLASS` window property will by default be set to the window title +/// passed to this function. The instance part will use the contents of the `RESOURCE_NAME` +/// environment variable, if present and not empty, or fall back to the window title. Set the glfw.x11_class_name +/// and glfw.x11_instance_name window hints to override this. +/// +/// wayland: Compositors should implement the xdg-decoration protocol for GLFW to decorate the +/// window properly. If this protocol isn't supported, or if the compositor prefers client-side +/// decorations, a very simple fallback frame will be drawn using the wp_viewporter protocol. A +/// compositor can still emit close, maximize or fullscreen events, using for instance a keybind +/// mechanism. If neither of these protocols is supported, the window won't be decorated. +/// +/// wayland: A full screen window will not attempt to change the mode, no matter what the +/// requested size or refresh rate. +/// +/// wayland: Screensaver inhibition requires the idle-inhibit protocol to be implemented in the +/// user's compositor. +/// +/// @thread_safety This function must only be called from the main thread. +/// +/// see also: window_creation, glfw.Window.destroy +pub fn create(width: usize, height: usize, title: [*c]const u8, monitor: ?Monitor, share: ?Window) Error!Window { + const handle = c.glfwCreateWindow( + @intCast(c_int, width), + @intCast(c_int, height), + &title[0], + if (monitor) |m| m.handle else null, + if (share) |w| w.handle else null, + ); + try getError(); + return Window{ .handle = handle.? }; +} + test "defaultHints" { const glfw = @import("main.zig"); try glfw.init(); @@ -99,3 +229,17 @@ test "hintString" { try hintString(glfw.x11_class_name, "myclass"); } + +test "createWindow" { + const glfw = @import("main.zig"); + try glfw.init(); + defer glfw.terminate(); + + const window = glfw.Window.create(640, 480, "Hello, Zig!", null, null) catch |err| { + // return without fail, because most of our CI environments are headless / we cannot open + // windows on them. + std.debug.print("note: failed to create window: {}\n", .{err}); + return; + }; + c.glfwDestroyWindow(window.handle); +}