| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400 |
- local ffi = require 'ffi'
- local C = ffi.os == 'Windows' and ffi.load('glfw3') or ffi.C
- local C_str = ffi.string
- ffi.cdef [[
- enum {
- GLFW_RESIZABLE = 0x00020003,
- GLFW_VISIBLE = 0x00020004,
- GLFW_DECORATED = 0x00020005,
- GLFW_FLOATING = 0x00020007
- };
- typedef struct {
- int width;
- int height;
- unsigned char* pixels;
- } GLFWimage;
- typedef struct GLFWvidmode {
- int width;
- int height;
- int refreshRate;
- } GLFWvidmode;
- typedef struct GLFWwindow GLFWwindow;
- GLFWwindow* os_get_glfw_window(void);
-
- typedef struct GLFWmonitor GLFWmonitor;
- GLFWmonitor** glfwGetMonitors(int *count);
- GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
- GLFWmonitor* glfwGetPrimaryMonitor(void);
- void glfwGetMonitorPos(GLFWmonitor* monitor, int *xpos, int *ypos);
- const char* glfwGetMonitorName(GLFWmonitor* monitor);
- const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
- void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
- void glfwGetMonitorWorkarea(GLFWmonitor *monitor, int *xpos, int *ypos, int *width, int *height);
-
- // icon
- void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage *images);
-
- // attributes
- void glfwSetWindowAttrib(GLFWwindow* window, int attrib, int value); //+
- int glfwGetWindowAttrib(GLFWwindow* window, int attrib); //+
-
- // size & limits
- void glfwSetWindowSize(GLFWwindow* window, int width, int height); //-
- void glfwGetWindowSize(GLFWwindow* window, int *width, int *height); //-
- void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); //-
-
- // position
- void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);
- void glfwGetWindowPos(GLFWwindow* window, int *xpos, int *ypos);
-
- // minimize maximize restore
- void glfwMaximizeWindow(GLFWwindow* window);
- void glfwIconifyWindow(GLFWwindow *window);
- void glfwRestoreWindow(GLFWwindow *window);
-
- // title
- void glfwSetWindowTitle(GLFWwindow* window, const char* title);
-
- // visible
- void glfwShowWindow(GLFWwindow* window);
- void glfwHideWindow(GLFWwindow* window);
-
- // focus
- void glfwFocusWindow(GLFWwindow* window);
-
- // attention
- void glfwRequestWindowAttention(GLFWwindow* window);
-
- // opacity
- void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
- float glfwGetWindowOpacity(GLFWwindow* window);
- // callbacks
- typedef void(*GLFWwindowsizefun) (GLFWwindow*, int, int); // size changed
- GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwindowsizefun callback );
- typedef void(*GLFWwindowmaximizefun) (GLFWwindow*, int); // maximize
- GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window, GLFWwindowmaximizefun callback);
- typedef void(*GLFWwindowposfun) (GLFWwindow*, int, int); // position changed
- GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindowposfun callback);
- typedef void(* GLFWdropfun) (GLFWwindow*, int, const char *[]);
- GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun callback);
-
- ]]
- local W = ffi.C.os_get_glfw_window()
- local window = {}
- local __monitors
- ---------------------------------------------------------------------------------------------------------------
- local __params = { -- default parameters list
- title = 'LÖVR',
- icon = nil,
- fullscreen = false,
- fullscreentype = "desktop",
- width = 1080,
- height = 600,
- minwidth = 320,
- minheight = 240,
- x = nil,
- y = nil,
- display = 1,
- centered = false,
- topmost = false,
- borderless = false,
- resizable = false,
- opacity = 1,
- vsync = 1,
- msaa = 0
- }
- if conf then
- for k,v in pairs(conf) do
- __params[k] = v
- end
- if type(__params.icon) == 'string' then
- __params.icon = lovr.data.newImage(__params.icon, false)
- end
- conf = nil
- end
- ---------------------------------------------------------------------------------------------------------------
- function window.getDisplayCount()
- local count = ffi.new('int[1]')
- __monitors = C.glfwGetMonitors(count)
- return count[0]
- end
- local function check_monitor( index, throwerr )
- if type(index) ~= 'number' then
- if throwerr then
- error('Bad argument #1: number expected got ' .. type(index), 3)
- else
- return false
- end
- end
- local dcnt = window.getDisplayCount()
- if index < 1 or index > dcnt then
- if throwerr then
- error('Invalid display index: ' .. tostring(index), 3)
- else
- return false
- end
- end
- return true
- end
- function window.getDisplayName( index )
- check_monitor( index, true )
- return C_str(C.glfwGetMonitorName( __monitors[index-1] ))
- end
- function window.getDisplayDimensions( index )
- check_monitor( index, true )
- local screenmode = C.glfwGetVideoMode( __monitors[index-1] )
- return screenmode.width, screenmode.height
- end
- ---------------------------------------------------------------------------------------------------------------
- function window.setIcon( source )
- if not source then
- C.glfwSetWindowIcon(W, 0, nil)
- __params.icon = nil
- return
- end
- if type(source) == 'string' then
- source = lovr.data.newImage(source, false)
- elseif tostring(source) ~= 'Image' then
- error('Bad argument #1 to setIcon (Image expected)', 2)
- end
- __params.icon = source
- local icon = ffi.new('GLFWimage', source:getWidth(), source:getHeight(), source:getBlob():getPointer())
- C.glfwSetWindowIcon(W, 1, icon)
- end
- function window.getIcon()
- return tostring(__params.icon) == 'Image' and __params.icon or nil
- end
- ---------------------------------------------------------------------------------------------------------------
- function window.setOpacity( value )
- value = math.max(0, math.min(value, 1))
- C.glfwSetWindowOpacity(W, value)
- end
- function window.getOpacity()
- return C.glfwGetWindowOpacity(W)
- end
- ---------------------------------------------------------------------------------------------------------------
- function window.setPosition( x,y )
- C.glfwSetWindowPos(W, x or 0, y or 0)
- end
- function window.getPosition()
- local x, y = ffi.new('int[1]'), ffi.new('int[1]')
- C.glfwGetWindowPos(W, x, y)
- return x[0], y[0]
- end
- ---------------------------------------------------------------------------------------------------------------
- function window.maximize()
- C.glfwMaximizeWindow(W)
- end
- function window.minimize()
- C.glfwIconifyWindow(W)
- end
- function window.restore()
- C.glfwRestoreWindow(W)
- end
- function window.focus()
- C.glfwFocusWindow(W)
- end
- function window.requestAttention()
- C.glfwRequestWindowAttention(W)
- end
- ---------------------------------------------------------------------------------------------------------------
- function window.setTitle( title )
- C.glfwSetWindowTitle(W, title)
- __params.title = title
- end
- function window.getTitle()
- return __params.title
- end
- ---------------------------------------------------------------------------------------------------------------
- function window.visible( state )
- if state then C.glfwShowWindow(W)
- else C.glfwHideWindow(W) end
- end
- function window.isVisible()
- return C.glfwGetWindowAttrib(W, C.GLFW_VISIBLE) == 1
- end
- ---------------------------------------------------------------------------------------------------------------
- function window.setFullscreen( state, fstype, index )
- index = index or 1
- index = check_monitor(index) and index-1 or 0
- local screenmode = C.glfwGetVideoMode( __monitors[index] )
- if state then
- assert(fstype == 'desktop' or fstype == 'exclusive', 'Invalid fullscreen type \''..tostring(fstype)..'\', expected one of : \'exclusive\' or \'desktop\'')
-
- if fstype == 'desktop' then
- C.glfwSetWindowAttrib(W, C.GLFW_DECORATED, 0)
- local mx, my = ffi.new('int[1]'), ffi.new('int[1]')
- C.glfwGetMonitorPos(__monitors[index], mx, my)
- C.glfwSetWindowMonitor(W, nil, mx[0],my[0], screenmode.width, screenmode.height, 0)
- elseif fstype == 'exclusive' then
- C.glfwSetWindowMonitor(W, __monitors[index], 0,0, screenmode.width, screenmode.height, 0)
- end
- __params.fullscreentype = fstype
- __params.fullscreen = true
- else
- __params.fullscreen = false
- __params.fullscreentype = nil
- if __params.x == nil or __params.y == nil then
- __params.x = math.random(0, screenmode.width*0.3)
- __params.y = math.random(0, screenmode.height*0.3)
- centered = false
- end
- C.glfwSetWindowAttrib(W, C.GLFW_DECORATED, __params.borderless and 0 or 1)
- C.glfwSetWindowMonitor(W, nil, __params.x, __params.y, __params.width, __params.height, 0)
- end
- end
- function window.getFullscreen()
- __params.fullscreen = C.glfwGetWindowMonitor(W) ~= nil
- return __params.fullscreen, __params.fullscreentype
- end
- ---------------------------------------------------------------------------------------------------------------
- function window.getMode()
- local flags = {}
- flags.fullscreen = C.glfwGetWindowMonitor(W) ~= nil
- flags.fullscreentype = __params.fullscreentype
- flags.x, flags.y = ffi.new('int[1]'), ffi.new('int[1]')
- C.glfwGetWindowPos(W, flags.x, flags.y)
- flags.x, flags.y = flags.x[0], flags.y[0]
- local width, height = ffi.new('int[1]'), ffi.new('int[1]')
- C.glfwGetWindowSize(W, width, height)
- width, height = width[0], height[0]
- flags.msaa = __params.msaa
- flags.vsync = __params.vsync
- flags.topmost = C.glfwGetWindowAttrib(W, C.GLFW_FLOATING) == 1
- flags.opacity = C.glfwGetWindowOpacity(W)
- flags.borderless = C.glfwGetWindowAttrib(W, C.GLFW_DECORATED) == 0
- flags.resizable = C.glfwGetWindowAttrib(W, C.GLFW_RESIZABLE) == 1
- flags.centered = __params.centered
- flags.display = __params.display
- flags.minwidth = __params.minwidth
- flags.minheight = __params.minheight
-
- return width, height, flags
- end
- function window.setMode( width, height, flags )
- if flags then
- local _, _, mode = window.getMode()
- for k,v in pairs(mode) do
- if not flags[k] or flags[k] == nil then
- flags[k] = v
- end
- end
- flags.display = check_monitor(flags.display) and flags.display or 1
- if flags.centered then
- local screenmode = C.glfwGetVideoMode( __monitors[flags.display-1] )
- local mx, my = ffi.new('int[1]'), ffi.new('int[1]')
- C.glfwGetMonitorPos(__monitors[flags.display-1], mx, my)
- flags.x = mx[0] + screenmode.width*0.5 - width*0.5
- flags.y = my[0] + screenmode.height*0.5 - height*0.5
- end
- C.glfwSetWindowPos(W, flags.x, flags.y)
-
- C.glfwSetWindowSizeLimits(W, flags.minwidth, flags.minheight, -1, -1)
- C.glfwSetWindowAttrib(W, C.GLFW_DECORATED, flags.borderless and 0 or 1)
- C.glfwSetWindowAttrib(W, C.GLFW_FLOATING, flags.topmost and 1 or 0)
- C.glfwSetWindowAttrib(W, C.GLFW_RESIZABLE, flags.resizable and 1 or 0)
- flags.opacity = math.max(0, math.min(flags.opacity, 1))
- C.glfwSetWindowOpacity(W, flags.opacity)
- if flags.fullscreen then
- window.setFullscreen(flags.fullscreen, flags.fullscreentype, flags.display)
- else
- C.glfwSetWindowSize(W, width, height)
- end
- __params.width = width
- __params.height = height
- for k,v in pairs(flags) do
- __params[k] = v
- end
- else
- C.glfwSetWindowSize(W, width, height)
- end
- end
- ---------------------------------------------------------------------------------------------------------------
- C.glfwSetWindowMaximizeCallback(W, function( target, maximized )
- local width, height = ffi.new('int[1]'), ffi.new('int[1]')
- C.glfwGetWindowSize(W, width, height)
- lovr.event.push('maximized', maximized == 1, width[0], height[0])
- end)
- C.glfwSetWindowPosCallback(W, function( target, x,y )
- if lovr.windowmoved then
- lovr.windowmoved(x, y)
- end
- end)
- C.glfwSetDropCallback(W, function( target, count, c_paths )
- if lovr.dragdrop then
- local paths = {}
- for i=0, count-1 do
- table.insert(paths, C_str(c_paths[i]))
- end
- lovr.dragdrop(paths)
- end
- end)
- return window
|