Skip to content

Instantly share code, notes, and snippets.

@mikesart
Created July 15, 2014 00:28
Show Gist options
  • Save mikesart/63ce0e64f85ce10b5a50 to your computer and use it in GitHub Desktop.
Save mikesart/63ce0e64f85ce10b5a50 to your computer and use it in GitHub Desktop.
//-----------------------------------------------------------------------------
// Purpose: Returns bounds of the usable workspace area, including multiple monitors
//-----------------------------------------------------------------------------
void CLinuxSurface::GetWorkspaceBounds( int &x0, int &y0, int &x1, int &y1, VPANEL panel )
{
// Build list of monitors
CUtlVector<XineramaScreenInfo> monitors;
GetMonitorList(monitors);
// Get the bounds of the window we're dealing with.
int px = 0, py = 0, pw = 0, pt = 0;
if ( panel )
{
panel = GetContextPanelForChildPanel( panel );
if ( panel )
{
g_pIPanel->GetPos( panel, px, py );
g_pIPanel->GetSize( panel, pw, pt );
}
}
// Work out which monitor best matches the window.
int iBestMonitor = 0;
int nBestIntersection = 0;
for ( int i = 0; i < monitors.Count(); i++ )
{
XineramaScreenInfo &monitorInfo = monitors[i];
// Work out how much the monitor and the rectangle intersect.
int nIntersectX = MIN( px + pw, monitorInfo.x_org + monitorInfo.width ) - MAX( px, monitorInfo.x_org );
int nIntersectY = MIN( py + pt, monitorInfo.y_org + monitorInfo.height ) - MAX( py, monitorInfo.y_org );
// both intersections should be turned into 0 if they are negative
nIntersectX = nIntersectX > 0 ? nIntersectX : 0;
nIntersectY = nIntersectY > 0 ? nIntersectY : 0;
int nIntersection = nIntersectX * nIntersectY;
if ( nIntersection > nBestIntersection )
{
nBestIntersection = nIntersection;
iBestMonitor = i;
}
// "xrandr --primary" has the effect of setting the specified
// output as the first monitor returned by XineramaQueryScreens.
// So we use monitor 0 as the primary if there is no
// intersection.
}
// we've found the best monitor, return it
XineramaScreenInfo &monitorInfo = monitors[iBestMonitor];
x0 = monitorInfo.x_org;
x1 = monitorInfo.x_org + monitorInfo.width;
y0 = monitorInfo.y_org;
y1 = monitorInfo.y_org + monitorInfo.height;
}
//-----------------------------------------------------------------------------
// Purpose: Returns the bounds of each monitor
//-----------------------------------------------------------------------------
bool CLinuxSurface::GetMonitorList(CUtlVector<XineramaScreenInfo >& monitorList)
{
// Check to see if Xinerama is supported. If so, we will use
// that to enumerate the monitors.
int event_base = 0;
int error_base = 0;
int major, minor;
int screencount;
XineramaScreenInfo *xinerama = NULL;
if ( XineramaQueryExtension(m_pXDisplay, &event_base, &error_base) &&
XineramaQueryVersion(m_pXDisplay, &major, &minor) &&
XineramaIsActive(m_pXDisplay) &&
((major != 0) || (minor != 0)))
{
xinerama = XineramaQueryScreens(m_pXDisplay, &screencount);
}
if ( !xinerama )
{
// No Xinerama, just return the bounds of the entire display.
XineramaScreenInfo screenInfo;
screenInfo.screen_number = 0;
screenInfo.x_org = screenInfo.y_org = 0;
screenInfo.width = DisplayWidth(m_pXDisplay, m_XScreen);
screenInfo.height = DisplayHeight(m_pXDisplay, m_XScreen);
WaitForX(m_pXDisplay, false);
monitorList.AddToTail(screenInfo);
return true;
}
// Copy the returned screen info into the supplied vector.
for (int i=0; i<screencount; i++)
{
monitorList.AddToTail(xinerama[i]);
}
XFree(xinerama);
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment