diff --git a/nw.lua b/nw.lua index c3d4bb3..f8db5bd 100644 --- a/nw.lua +++ b/nw.lua @@ -997,8 +997,8 @@ end function window:_hittest(mx, my) local where if self:_can_set_rect() and self:resizeable() then - local ho, vo = 8, 8 --TODO: expose this? - local co = (vo + ho) / 2 + local ho, vo = 8, 8 --TODO: expose these? + local co = vo + ho --...and this (corner radius) local w, h = self:client_size() where = app:_resize_area_hit(mx, my, w, h, ho, vo, co) end @@ -1009,7 +1009,6 @@ end function window:_init_manual_resize() if self:frame() ~= 'none' then return end - if app:ver'OSX' then return end --TODO: remove this local resizing, where, sides, dx, dy @@ -1042,11 +1041,7 @@ function window:_init_manual_resize() self:cursor'arrow' end else - if app:ver'X' then - mx, my = app.backend:_get_mouse_pos() - else - mx, my = self:to_screen(mx, my) - end + mx, my = app:mouse'pos' --need absolute pos because X is async if where == 'move' then local w, h = self:client_size() self:frame_rect(mx + dx, my + dy, w, h) @@ -1361,6 +1356,18 @@ end --mouse ---------------------------------------------------------------------- +function app:mouse(var) + if var == 'inside' then + return true + elseif var == 'pos' then + return self.backend:get_mouse_pos() + elseif var == 'x' then + return (self.backend:get_mouse_pos()) + elseif var == 'y' then + return select(2, self.backend:get_mouse_pos()) + end +end + function window:mouse(var) if not self:_can_get_rect() then return end local inside = self._mouse.inside diff --git a/nw.md b/nw.md index 6152348..31b71ba 100644 --- a/nw.md +++ b/nw.md @@ -167,7 +167,7 @@ __views__ `view:moved(x, y, oldx, oldy)` event: view was moved `view:resized(w, h, oldw, oldh)` event: view was resized __mouse__ -`win/view:mouse(var) -> val` mouse state: _x, y, pos, inside, left, right, middle, x1, x2_ +`app/win/view:mouse(var) -> val` mouse state: _x, y, pos, inside, left, right, middle, x1, x2_ `win/view:mouseenter(x, y)` event: mouse entered the client area of the window `win/view:mouseleave()` event: mouse left the client area of the window `win/view:mousemove(x, y)` event: mouse was moved diff --git a/nw_cocoa.lua b/nw_cocoa.lua index f5de966..4863cdf 100644 --- a/nw_cocoa.lua +++ b/nw_cocoa.lua @@ -171,9 +171,7 @@ function window:new(app, frontend, t) not toolbox and t.minimizable and objc.NSMiniaturizableWindowMask or 0, t.resizeable and objc.NSResizableWindowMask or 0) else - style = bit.bor( - objc.NSBorderlessWindowMask, - t.resizeable and objc.NSResizableWindowMask or 0) + style = objc.NSBorderlessWindowMask --for frameless windows we have to handle maximization manually. self._frameless = true end @@ -1315,18 +1313,24 @@ local hi_cursors = { } --resize sides and corners -cursors.topleft = hi_cursors.size_diag2 -cursors.topright = hi_cursors.size_diag1 -cursors.bottomleft = hi_cursors.size_diag1 -cursors.bottomright = hi_cursors.size_diag2 -cursors.top = hi_cursors.size_v -cursors.bottom = hi_cursors.size_v -cursors.left = hi_cursors.size_h -cursors.right = hi_cursors.size_h +hi_cursors.topleft = hi_cursors.size_diag2 +hi_cursors.topright = hi_cursors.size_diag1 +hi_cursors.bottomleft = hi_cursors.size_diag1 +hi_cursors.bottomright = hi_cursors.size_diag2 +hi_cursors.top = hi_cursors.size_v +hi_cursors.bottom = hi_cursors.size_v +hi_cursors.left = hi_cursors.size_h +hi_cursors.right = hi_cursors.size_h + +local cursors_basepath = glue.memoize(function() + local basepath = objc.findframework'ApplicationServices.HIServices' + if not basepath then return end + return basepath..'/Versions/Current/Resources/cursors' +end) local load_hicursor = objc.memoize(function(name) - basepath = basepath or objc.findframework( - 'ApplicationServices.HIServices/Versions/Current/Resources/cursors') + local basepath = cursors_basepath() + if not basepath then return end local curpath = string.format('%s/%s/cursor.pdf', basepath, name) local infopath = string.format('%s/%s/info.plist', basepath, name) local image = objc.NSImage:alloc():initByReferencingFile(curpath) @@ -1354,7 +1358,8 @@ function Window:cursorUpdate(event) if self:nw_clientarea_hit(event) then local cursor, visible = self.frontend:cursor() if visible then - load_cursor(cursor):set() + local cursor = load_cursor(cursor) or load_cursor'arrow' + cursor:set() objc.NSCursor:unhide() else objc.NSCursor:hide() @@ -1640,7 +1645,7 @@ function app:key(name) end end ---mouse/settings ------------------------------------------------------------- +--mouse/app ------------------------------------------------------------------ function app:double_click_time() return objc.NSEvent:doubleClickInterval() --seconds @@ -1650,6 +1655,17 @@ function app:double_click_target_area() return 4, 4 --like in Windows end +function app:get_mouse_pos() + --TODO: this returns the current mouse location outside of the event stream. + --We don't want that! We want the mouse location at "this event" time. Find a way! + local p = objc.NSEvent:mouseLocation() + return p.x, primary_screen_h() - p.y +end + +function app:set_mouse_pos() + --TODO +end + --rendering/bitmap ----------------------------------------------------------- --make a bitmap that can be painted on the current NSGraphicsContext. diff --git a/nw_demo.lua b/nw_demo.lua index 4aa2a7b..feff05c 100644 --- a/nw_demo.lua +++ b/nw_demo.lua @@ -315,13 +315,26 @@ function win:hittest(mx, my, where) self.max_hover = box2d.hit(mx, my, unpack(max_rect)) self.close_hover = box2d.hit(mx, my, unpack(close_rect)) self.titlebar_hover = - not where --the titlebar is below the invisible resize grips - and not self:ismaximized() - and not self:fullscreen() + not where --the titlebar is below the invisible resize grip and box2d.hit(mx, my, unpack(titlebar_rect)) - if self.min_hover or self.max_hover or self.close_hover then return false end - if self.titlebar_hover then return 'move' end + if self.min_hover or self.max_hover or self.close_hover then + return false --titlebar buttons are above the invisible resize grip + elseif self.titlebar_hover then + if self:ismaximized() or self:fullscreen() then return end + return 'move' + end +end + +function win:click(button, count) + if count == 2 and self.titlebar_hover then + if self:ismaximized() then + self:restore() + else + self:maximize() + end + return true + end end function win:mouseup(x, y) diff --git a/nw_winapi.lua b/nw_winapi.lua index cc1611a..e7e0a26 100644 --- a/nw_winapi.lua +++ b/nw_winapi.lua @@ -1137,6 +1137,15 @@ function app:double_click_target_area() return w, h end +function app:get_mouse_pos() + local p = winapi.GetCursorPos() + return p.x, p.y +end + +function app:set_mouse_pos(x, y) + winapi.SetCursorPos(x, y) +end + --TODO: get lost mouse events http://blogs.msdn.com/b/oldnewthing/archive/2012/03/14/10282406.aspx local function unpack_buttons(b) diff --git a/nw_xlib.lua b/nw_xlib.lua index 3004c64..1c1d6c2 100644 --- a/nw_xlib.lua +++ b/nw_xlib.lua @@ -1242,11 +1242,15 @@ function window:_setmouse(e) return m end -function app:_get_mouse_pos() +function app:get_mouse_pos() local x, y = xlib.query_pointer(xlib.screen.root) return x, y end +function app:set_mouse_pos(x, y) + --TODO +end + function window:ButtonPress(e) if self._disabled then return end if e.button == C.Button4 then --wheel up