This makes the code more readable, even though it almost doubles its size -- but the corresponding reduction in the number of preprocessor checks is still worth it.
360 lines
9.2 KiB
C++
360 lines
9.2 KiB
C++
///////////////////////////////////////////////////////////////////////////
|
|
// Name: src/gtk/display.cpp
|
|
// Author: Paul Cornett
|
|
// Created: 2014-04-17
|
|
// Copyright: (c) 2014 Paul Cornett
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "wx/wxprec.h"
|
|
|
|
#include "wx/private/display.h"
|
|
|
|
#include "wx/gtk/private/wrapgtk.h"
|
|
#ifdef GDK_WINDOWING_X11
|
|
#ifndef __WXGTK4__
|
|
#include "wx/unix/private/displayx11.h"
|
|
|
|
#define wxGTK_HAVE_X11_DISPLAY
|
|
#endif
|
|
|
|
#include <gdk/gdkx.h>
|
|
#endif
|
|
|
|
// This file is not used at all when using Win32.
|
|
#if !defined(GDK_WINDOWING_WIN32)
|
|
|
|
GdkWindow* wxGetTopLevelGDK();
|
|
|
|
// There are 2 quite different implementations here: one for GTK+ 4 and the
|
|
// other one for the previous versions.
|
|
|
|
#ifdef __WXGTK4__
|
|
|
|
static inline GdkDisplay* GetDisplay()
|
|
{
|
|
return gdk_window_get_display(wxGetTopLevelGDK());
|
|
}
|
|
|
|
// This class is always defined as it's used for the main display even when
|
|
// wxUSE_DISPLAY == 0.
|
|
class wxDisplayImplGTK : public wxDisplayImpl
|
|
{
|
|
typedef wxDisplayImpl base_type;
|
|
public:
|
|
wxDisplayImplGTK(unsigned i);
|
|
virtual wxRect GetGeometry() const wxOVERRIDE;
|
|
virtual wxRect GetClientArea() const wxOVERRIDE;
|
|
|
|
#if wxUSE_DISPLAY
|
|
virtual bool IsPrimary() const wxOVERRIDE;
|
|
virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const wxOVERRIDE;
|
|
virtual wxVideoMode GetCurrentMode() const wxOVERRIDE;
|
|
virtual bool ChangeMode(const wxVideoMode& mode) wxOVERRIDE;
|
|
#endif // wxUSE_DISPLAY
|
|
|
|
GdkMonitor* const m_monitor;
|
|
};
|
|
|
|
// This class is only defined when we're built with full display support.
|
|
#if wxUSE_DISPLAY
|
|
class wxDisplayFactoryGTK: public wxDisplayFactory
|
|
{
|
|
public:
|
|
virtual wxDisplayImpl* CreateDisplay(unsigned n) wxOVERRIDE;
|
|
virtual unsigned GetCount() wxOVERRIDE;
|
|
virtual int GetFromPoint(const wxPoint& pt) wxOVERRIDE;
|
|
};
|
|
|
|
wxDisplayImpl* wxDisplayFactoryGTK::CreateDisplay(unsigned n)
|
|
{
|
|
return new wxDisplayImplGTK(n);
|
|
}
|
|
|
|
unsigned wxDisplayFactoryGTK::GetCount()
|
|
{
|
|
return gdk_display_get_n_monitors(::GetDisplay());
|
|
}
|
|
|
|
int wxDisplayFactoryGTK::GetFromPoint(const wxPoint& pt)
|
|
{
|
|
GdkRectangle rect;
|
|
GdkDisplay* display = ::GetDisplay();
|
|
GdkMonitor* monitor = gdk_display_get_monitor_at_point(display, pt.x, pt.y);
|
|
gdk_monitor_get_geometry(monitor, &rect);
|
|
if (wxRect(rect.x, rect.y, rect.width, rect.height).Contains(pt))
|
|
{
|
|
for (unsigned i = gdk_display_get_n_monitors(display); i--;)
|
|
{
|
|
if (gdk_display_get_monitor(display, i) == monitor)
|
|
return i;
|
|
}
|
|
}
|
|
return wxNOT_FOUND;
|
|
}
|
|
#endif // wxUSE_DISPLAY
|
|
|
|
wxDisplayImplGTK::wxDisplayImplGTK(unsigned i)
|
|
: base_type(i)
|
|
, m_monitor(gdk_display_get_monitor(GetDisplay(), i))
|
|
{
|
|
}
|
|
|
|
wxRect wxDisplayImplGTK::GetGeometry() const
|
|
{
|
|
GdkRectangle rect;
|
|
gdk_monitor_get_geometry(m_monitor, &rect);
|
|
return wxRect(rect.x, rect.y, rect.width, rect.height);
|
|
}
|
|
|
|
wxRect wxDisplayImplGTK::GetClientArea() const
|
|
{
|
|
GdkRectangle rect;
|
|
gdk_monitor_get_workarea(m_monitor, &rect);
|
|
return wxRect(rect.x, rect.y, rect.width, rect.height);
|
|
}
|
|
|
|
#if wxUSE_DISPLAY
|
|
bool wxDisplayImplGTK::IsPrimary() const
|
|
{
|
|
return gdk_monitor_is_primary(m_monitor) != 0;
|
|
}
|
|
|
|
wxArrayVideoModes
|
|
wxDisplayImplGTK::GetModes(const wxVideoMode& WXUNUSED(mode)) const
|
|
{
|
|
return wxArrayVideoModes();
|
|
}
|
|
|
|
wxVideoMode wxDisplayImplGTK::GetCurrentMode() const
|
|
{
|
|
return wxVideoMode();
|
|
}
|
|
|
|
bool wxDisplayImplGTK::ChangeMode(const wxVideoMode& WXUNUSED(mode))
|
|
{
|
|
return false;
|
|
}
|
|
#endif // wxUSE_DISPLAY
|
|
|
|
#else // !__WXGTK4__
|
|
|
|
#ifdef __WXGTK3__
|
|
|
|
static inline bool gdk_is_x11_screen(GdkScreen* screen)
|
|
{
|
|
return GDK_IS_X11_SCREEN(screen);
|
|
}
|
|
|
|
#else // !__WXGTK3__
|
|
|
|
static inline int wx_gdk_screen_get_primary_monitor(GdkScreen* screen)
|
|
{
|
|
int monitor = 0;
|
|
#if GTK_CHECK_VERSION(2,20,0)
|
|
if (wx_is_at_least_gtk2(20))
|
|
monitor = gdk_screen_get_primary_monitor(screen);
|
|
#endif
|
|
return monitor;
|
|
}
|
|
#define gdk_screen_get_primary_monitor wx_gdk_screen_get_primary_monitor
|
|
|
|
static inline bool gdk_is_x11_screen(GdkScreen* WXUNUSED(screen))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
#endif // __WXGTK3__/!__WXGTK3__
|
|
|
|
static inline void
|
|
wx_gdk_screen_get_monitor_workarea(GdkScreen* screen, int monitor, GdkRectangle* dest)
|
|
{
|
|
wxGCC_WARNING_SUPPRESS(deprecated-declarations)
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
|
if (gtk_check_version(3,4,0) == NULL)
|
|
gdk_screen_get_monitor_workarea(screen, monitor, dest);
|
|
else
|
|
#endif
|
|
{
|
|
gdk_screen_get_monitor_geometry(screen, monitor, dest);
|
|
#ifdef wxGTK_HAVE_X11_DISPLAY
|
|
if ( gdk_is_x11_screen(screen) )
|
|
{
|
|
GdkRectangle rect = { 0, 0, 0, 0 };
|
|
wxGetWorkAreaX11(GDK_SCREEN_XSCREEN(screen),
|
|
rect.x, rect.y, rect.width, rect.height);
|
|
// in case _NET_WORKAREA result is too large
|
|
if (rect.width && rect.height)
|
|
gdk_rectangle_intersect(dest, &rect, dest);
|
|
}
|
|
#endif // wxGTK_HAVE_X11_DISPLAY
|
|
}
|
|
wxGCC_WARNING_RESTORE()
|
|
}
|
|
#define gdk_screen_get_monitor_workarea wx_gdk_screen_get_monitor_workarea
|
|
|
|
static inline GdkScreen* GetScreen()
|
|
{
|
|
return gdk_window_get_screen(wxGetTopLevelGDK());
|
|
}
|
|
|
|
class wxDisplayImplGTK : public wxDisplayImpl
|
|
{
|
|
typedef wxDisplayImpl base_type;
|
|
public:
|
|
wxDisplayImplGTK(unsigned i);
|
|
virtual wxRect GetGeometry() const wxOVERRIDE;
|
|
virtual wxRect GetClientArea() const wxOVERRIDE;
|
|
|
|
#if wxUSE_DISPLAY
|
|
virtual bool IsPrimary() const wxOVERRIDE;
|
|
virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const wxOVERRIDE;
|
|
virtual wxVideoMode GetCurrentMode() const wxOVERRIDE;
|
|
virtual bool ChangeMode(const wxVideoMode& mode) wxOVERRIDE;
|
|
#endif // wxUSE_DISPLAY
|
|
|
|
GdkScreen* const m_screen;
|
|
};
|
|
|
|
#if wxUSE_DISPLAY
|
|
class wxDisplayFactoryGTK: public wxDisplayFactory
|
|
{
|
|
public:
|
|
virtual wxDisplayImpl* CreateDisplay(unsigned n) wxOVERRIDE;
|
|
virtual unsigned GetCount() wxOVERRIDE;
|
|
virtual int GetFromPoint(const wxPoint& pt) wxOVERRIDE;
|
|
};
|
|
|
|
wxGCC_WARNING_SUPPRESS(deprecated-declarations)
|
|
|
|
wxDisplayImpl* wxDisplayFactoryGTK::CreateDisplay(unsigned n)
|
|
{
|
|
return new wxDisplayImplGTK(n);
|
|
}
|
|
|
|
unsigned wxDisplayFactoryGTK::GetCount()
|
|
{
|
|
return gdk_screen_get_n_monitors(GetScreen());
|
|
}
|
|
|
|
int wxDisplayFactoryGTK::GetFromPoint(const wxPoint& pt)
|
|
{
|
|
GdkRectangle rect;
|
|
GdkScreen* screen = GetScreen();
|
|
int monitor = gdk_screen_get_monitor_at_point(screen, pt.x, pt.y);
|
|
gdk_screen_get_monitor_geometry(screen, monitor, &rect);
|
|
if (!wxRect(rect.x, rect.y, rect.width, rect.height).Contains(pt))
|
|
monitor = wxNOT_FOUND;
|
|
return monitor;
|
|
}
|
|
#endif // wxUSE_DISPLAY
|
|
|
|
wxDisplayImplGTK::wxDisplayImplGTK(unsigned i)
|
|
: base_type(i)
|
|
, m_screen(GetScreen())
|
|
{
|
|
}
|
|
|
|
wxRect wxDisplayImplGTK::GetGeometry() const
|
|
{
|
|
GdkRectangle rect;
|
|
gdk_screen_get_monitor_geometry(m_screen, m_index, &rect);
|
|
return wxRect(rect.x, rect.y, rect.width, rect.height);
|
|
}
|
|
|
|
wxRect wxDisplayImplGTK::GetClientArea() const
|
|
{
|
|
GdkRectangle rect;
|
|
gdk_screen_get_monitor_workarea(m_screen, m_index, &rect);
|
|
return wxRect(rect.x, rect.y, rect.width, rect.height);
|
|
}
|
|
|
|
#if wxUSE_DISPLAY
|
|
bool wxDisplayImplGTK::IsPrimary() const
|
|
{
|
|
return gdk_screen_get_primary_monitor(m_screen) == int(m_index);
|
|
}
|
|
|
|
wxArrayVideoModes wxDisplayImplGTK::GetModes(const wxVideoMode& mode) const
|
|
{
|
|
wxArrayVideoModes modes;
|
|
#ifdef wxGTK_HAVE_X11_DISPLAY
|
|
if ( gdk_is_x11_screen(m_screen) )
|
|
{
|
|
Display* display = GDK_DISPLAY_XDISPLAY(gdk_screen_get_display(m_screen));
|
|
#ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
|
|
int nScreen = gdk_x11_screen_get_screen_number(m_screen);
|
|
modes = wxXF86VidMode_GetModes(mode, display, nScreen);
|
|
#else
|
|
modes = wxX11_GetModes(this, mode, display);
|
|
#endif
|
|
}
|
|
#else
|
|
wxUnusedVar(mode);
|
|
#endif
|
|
return modes;
|
|
}
|
|
|
|
wxVideoMode wxDisplayImplGTK::GetCurrentMode() const
|
|
{
|
|
wxVideoMode mode;
|
|
#if defined(wxGTK_HAVE_X11_DISPLAY) && defined(HAVE_X11_EXTENSIONS_XF86VMODE_H)
|
|
if ( gdk_is_x11_screen(m_screen) )
|
|
{
|
|
Display* display = GDK_DISPLAY_XDISPLAY(gdk_screen_get_display(m_screen));
|
|
int nScreen = gdk_x11_screen_get_screen_number(m_screen);
|
|
mode = wxXF86VidMode_GetCurrentMode(display, nScreen);
|
|
}
|
|
#endif
|
|
return mode;
|
|
}
|
|
|
|
bool wxDisplayImplGTK::ChangeMode(const wxVideoMode& mode)
|
|
{
|
|
bool success = false;
|
|
#if defined(wxGTK_HAVE_X11_DISPLAY) && defined(HAVE_X11_EXTENSIONS_XF86VMODE_H)
|
|
if ( gdk_is_x11_screen(m_screen) )
|
|
{
|
|
Display* display = GDK_DISPLAY_XDISPLAY(gdk_screen_get_display(m_screen));
|
|
int nScreen = gdk_x11_screen_get_screen_number(m_screen);
|
|
success = wxXF86VidMode_ChangeMode(mode, display, nScreen);
|
|
}
|
|
#else
|
|
wxUnusedVar(mode);
|
|
#endif
|
|
return success;
|
|
}
|
|
|
|
wxGCC_WARNING_RESTORE()
|
|
|
|
#endif // wxUSE_DISPLAY
|
|
|
|
#endif // __WXGTK4__/!__WXGTK4__
|
|
|
|
#if wxUSE_DISPLAY
|
|
|
|
wxDisplayFactory* wxDisplay::CreateFactory()
|
|
{
|
|
return new wxDisplayFactoryGTK;
|
|
}
|
|
|
|
#else // !wxUSE_DISPLAY
|
|
|
|
class wxDisplayFactorySingleGTK : public wxDisplayFactorySingle
|
|
{
|
|
protected:
|
|
virtual wxDisplayImpl *CreateSingleDisplay()
|
|
{
|
|
return new wxDisplayImplGTK(0);
|
|
}
|
|
};
|
|
|
|
wxDisplayFactory* wxDisplay::CreateFactory()
|
|
{
|
|
return new wxDisplayFactorySingleGTK;
|
|
}
|
|
|
|
#endif // wxUSE_DISPLAY/!wxUSE_DISPLAY
|
|
|
|
#endif // !defined(GDK_WINDOWING_WIN32)
|