Drag Popup Outside of Project

I have 2 monitors and I have a popup that I would like to be able to drag to a different screen and keep the main project on the other display. However, the popup dragging is constrained to the display that the project is displayed on.

Is there a way to allow the popup to be moved to the second monitor?

Not moved, but you can open another desktop instance on the second monitor, and have the popup open there.

Trying to do that now, but it's still stuck on my main monitor. inside the project. I can't even drag it on top of my docked window.

system.nav.desktop(1).openWindow('ALARMS - ACTIVE')

ALARMS - ACTIVE is a popup window

Ok, so not using a popup anymore, but I have a full-screen view of the window I want on another page, but I have no menu bar on the top to close it. I assume that the menu bar follows project properties, and that's why it's hidden?

system.gui.openDesktop(screen = 1, handle='Alarm Window')
system.nav.desktop('Alarm Window').openWindow('ALARMS - ACTIVE')

trying to use system.gui.closeDesktop('Alarm Window) on window close results in a java recursion limit error.

That's ugly. Definitely want to report that--recursion limit that isn't jython is always a bug.

1 Like

So, circling back to this again. I have one main client that will have multiple screens, but not all clients will have the same number of displays. The easy solution would be to allow popups to be dragged out of the vision client application and then they can be moved to whatever monitors are available.

If that's not an option, I might have to figure out how to script it to find how many monitors are available and provide a way to specify which monitor to open it on.

Thoughts?

system.gui.getScreens(), perhaps?

Ya, working on it

system.gui.getScreens() doesn't return the relative positions of the screens.

Use this one instead.

Thanks. Adjusting the script from this unfinished post, I have

openDesktops = len(system.gui.getDesktopHandles())
monitorData = Navigation.getScreens()
if openDesktops == 0 and len(monitorData) > 1:
	for desktopIndex, desktopWidth, desktopHeight, desktopX, desktopY in monitorData[1:]:
		handleName = "Desktop %d" %desktopIndex
		system.gui.openDesktop(screen=desktopIndex, handle=handleName, width=desktopWidth, height=desktopHeight, x=desktopX, y=desktopY).setAlwaysOnTop(False)
		#system.nav.desktop(handleName).swapTo('whatever/window/path')

Desktop 1 still opens on monitor 0 and desktop 2 is now not on any of the monitors.

Try it with just the screen indexes first. Then try to get fancy after that. :wink:

So Ignition thinks my screen 3 is screen 1? Do the screen numbers not match the numbering in my Windows display settings?

Correct, they do not (necessarily) match.

Well, not sure that it really matters in this case. The main window will be locked to fullscreen and I think I'll just use a button to open a maximized window that can be moved wherever the user wants.

This is what I came up with:

#base desktop handle
dHandle = 'Desktop '

#get handles
handles = system.gui.getDesktopHandles()

#no desktops open yet
if len(handles) == 0:
	nextIndex = 0
#other desktops open
else:
	#get list of the desktop indicies from the handle
	openDesktopIndicies = [int(handle.replace(dHandle,'')) for handle in handles]
	#get max index and increment for next index
	nextIndex = max(openDesktopIndicies)+1

#get the current window
window = system.nav.getCurrentWindow()

#open new desktop with current window
system.gui.openDesktop(handle=dHandle+str(nextIndex),windows = [window]).setAlwaysOnTop(False)

What I'm running into now is that with the project open in fullscreen mode, opening a new desktop is in fullscreen mode. How can I make it windowed mode for the new desktops?

Thinking I could do something with this script after opening the new desktop?

from javax.swing import JFrame

window = system.gui.getParentWindow(event)
while not isinstance(window, JFrame):
	window = window.getParent()
if window.isUndecorated():
	# Switch to windowed mode.
	window.dispose()
	window.setUndecorated(False)
	window.setExtendedState(JFrame.NORMAL)
	# Restore previous window size and location, if available.
	try:
		normalW = event.source.getClientProperty('normalW')
		normalH = event.source.getClientProperty('normalH')
		normalX = event.source.getClientProperty('normalX')
		normalY = event.source.getClientProperty('normalY')
		window.setSize(normalW, normalH)
		window.setLocation(normalX, normalY)
	except:
		pass
	window.setVisible(True)
else:
	# Store window size and location for restore.
	event.source.putClientProperty('normalW', window.size.width)
	event.source.putClientProperty('normalH', window.size.height)
	event.source.putClientProperty('normalX', window.x)
	event.source.putClientProperty('normalY', window.y)
	# Switch to full screen mode.
	window.dispose()
	window.setUndecorated(True)
	window.setExtendedState(JFrame.MAXIMIZED_BOTH)
	window.setVisible(True)

Just not sure how to use this with the new desktop and window

Since I already have the JFrame from system.gui.openDesktop(), I should be able to pass that directly to the function that I've placed in the project script library.

#base desktop handle
dHandle = 'Desktop '

#get handles
handles = system.gui.getDesktopHandles()

#no desktops open yet
if len(handles) == 0:
	nextIndex = 0
#other desktops open
else:
	#get list of the desktop indicies from the handle
	openDesktopIndicies = [int(handle.replace(dHandle,'')) for handle in handles]
	#get max index and increment for next index
	nextIndex = max(openDesktopIndicies)+1

#get the current window
window = system.nav.getCurrentWindow()

#open new desktop with current window
desktop = system.gui.openDesktop(handle=dHandle+str(nextIndex),windows = [window]).setAlwaysOnTop(False)

Navigation.desktopSwapToWindowedMode(desktop)
#pass desktop JFrame directly
def desktopSwapToWindowedMode(desktop):

	from javax.swing import JFrame
	
	window = desktop
#skip this because we already have the JFrame
#	window = system.gui.getParentWindow(event)
#	while not isinstance(window, JFrame):
#		window = window.getParent()
	if window.isUndecorated():
		# Switch to windowed mode.
		window.dispose()
		window.setUndecorated(False)
		window.setExtendedState(JFrame.NORMAL)
		# Restore previous window size and location, if available.
		try:
			normalW = event.source.getClientProperty('normalW')
			normalH = event.source.getClientProperty('normalH')
			normalX = event.source.getClientProperty('normalX')
			normalY = event.source.getClientProperty('normalY')
			window.setSize(normalW, normalH)
			window.setLocation(normalX, normalY)
		except:
			pass
		window.setVisible(True)
	else:
		# Store window size and location for restore.
		event.source.putClientProperty('normalW', window.size.width)
		event.source.putClientProperty('normalH', window.size.height)
		event.source.putClientProperty('normalX', window.x)
		event.source.putClientProperty('normalY', window.y)
		# Switch to full screen mode.
		window.dispose()
		window.setUndecorated(True)
		window.setExtendedState(JFrame.MAXIMIZED_BOTH)
		window.setVisible(True)

but I get an error at the first if statement

File "<module:Navigation>", line 146, in desktopSwapToWindowedMode
AttributeError: 'NoneType' object has no attribute 'isUndecorated'

That needs to be broken into two lines:

desktop = system.gui.openDesktop(handle=dHandle+str(nextIndex),windows = [window])
desktop.setAlwaysOnTop(False)

You are assigning the result of setAlwaysOnTop to desktop instead of the window object from system.gui.openDesktop

I do the same thing all the time with the dictionary .update method

2 Likes

I'm getting an error now when I try to swap the window back to fullscreen mode. It says event doesn't exist.

Button script:

desktop = Nav.getParentDesktop(system.gui.getParentWindow(event))

if Nav.desktopIsWindowedMode(desktop):
	Nav.desktopSwapDisplayMode(desktop)
else:
	Nav.desktopSwapDisplayMode(Nav.openNewDesktop())

Nav scripts:

def getParentDesktop(window):
	'''
		Get the parent desktop JFrame for supplied window.
		
		Args:
			window	(obj)		:	window on the desktop
			
		Returns:
			desktop	(JFrame)	:	window's parent desktop JFrame
	'''
	while not isinstance(window, JFrame):
		window = window.getParent()
		
	desktop = window
	
	return desktop
	
		
		
def desktopIsWindowedMode(window):
	'''
		Determine if a desktop is in windowed mode or not.
		
		Args:
			window	(ovj)		:	Window to determine if the parent desktop is in fullscreen or windowed mode
			
		Returns:
			isWindowMode	(BOOL)	:	True if desktop is in window mode
	'''
	
	#undecorated = fullscreen
	return not Nav.getParentDesktop(window).isUndecorated()
	
		
def openNewDesktop():
	'''
		Open a new desktop window
		
		Args:
			n/a
			
		Returns:
			desktop (JFrame)	:	newly opened desktop
	'''
	
	#base desktop handle
	dHandle = 'Desktop '
	
	#get handles
	handles = system.gui.getDesktopHandles()
	
	#no desktops open yet
	if len(handles) == 0:
	    nextIndex = 0
	#other desktops open
	else:
	    #get list of the desktop indicies from the handle
	    openDesktopIndicies = [int(handle.replace(dHandle,'')) for handle in handles]
	    #get max index and increment for next index
	    nextIndex = max(openDesktopIndicies)+1
	
	#get the current window
	window = system.nav.getCurrentWindow()
	
	#open new desktop with current window
	desktop = system.gui.openDesktop(handle=dHandle+str(nextIndex),windows = [window, 'Nav'])
	desktop.setAlwaysOnTop(False)
	
	return desktop
	
def desktopSwapDisplayMode(desktop):
    '''
        Swap the selected "desktop" to windowed/fullscreen mode from fullscreen/windowed mode.
        
        Args:
            desktop (JFrame)    :   JFrame of desktop to be swapped to windowed mode.
        
        Returns:
            n/a
    '''

    
    window = desktop
    if window.isUndecorated():
        # Switch to windowed mode.
        window.dispose()
        window.setUndecorated(False)
        window.setExtendedState(JFrame.NORMAL)
        # Restore previous window size and location, if available.
        try:
            normalW = event.source.getClientProperty('normalW')
            normalH = event.source.getClientProperty('normalH')
            normalX = event.source.getClientProperty('normalX')
            normalY = event.source.getClientProperty('normalY')
            window.setSize(normalW, normalH)
            window.setLocation(normalX, normalY)
        except:
            pass
        window.setVisible(True)
    else:
        # Store window size and location for restore.
        event.source.putClientProperty('normalW', window.size.width)
        event.source.putClientProperty('normalH', window.size.height)
        event.source.putClientProperty('normalX', window.x)
        event.source.putClientProperty('normalY', window.y)
        # Switch to full screen mode.
        window.dispose()
        window.setUndecorated(True)
        window.setExtendedState(JFrame.MAXIMIZED_BOTH)
        window.setVisible(True)

Change the argument in the desktopSwapDisplayMode library script, and get the desktop directly from there:

def desktopSwapDisplayMode(event):
        desktop = getParentDesktop(system.gui.getParentWindow(event))

Then, all of the event. stuff in that script will work without throwing an error. As it is currently written, event isn't defined in that function.

1 Like