Skip to content

Commit

Permalink
app:mouse'pos' API; custom-frame resizing for OSX
Browse files Browse the repository at this point in the history
  • Loading branch information
capr committed Sep 25, 2015
1 parent 95e89f6 commit 3165f98
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 30 deletions.
23 changes: 15 additions & 8 deletions nw.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion nw.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
46 changes: 31 additions & 15 deletions nw_cocoa.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -1640,7 +1645,7 @@ function app:key(name)
end
end

--mouse/settings -------------------------------------------------------------
--mouse/app ------------------------------------------------------------------

function app:double_click_time()
return objc.NSEvent:doubleClickInterval() --seconds
Expand All @@ -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.
Expand Down
23 changes: 18 additions & 5 deletions nw_demo.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
9 changes: 9 additions & 0 deletions nw_winapi.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 5 additions & 1 deletion nw_xlib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 3165f98

Please sign in to comment.