1 ///////////////////////////////////////////////////////////////////////////
2 // Name:        src/gtk/display.cpp
3 // Author:      Paul Cornett
4 // Created:     2014-04-17
5 // Copyright:   (c) 2014 Paul Cornett
6 // Licence:     wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
8 
9 #include "wx/wxprec.h"
10 
11 #if wxUSE_DISPLAY
12     #include "wx/display.h"
13     #include "wx/display_impl.h"
14 #endif
15 #include "wx/utils.h" // wxClientDisplayRect
16 
17 #include <gtk/gtk.h>
18 #ifdef GDK_WINDOWING_X11
19     #include <gdk/gdkx.h>
20 #endif
21 #include "wx/gtk/private/gtk2-compat.h"
22 
23 GtkWidget* wxGetRootWindow();
24 
25 //-----------------------------------------------------------------------------
26 
27 #if !(wxUSE_LIBHILDON || wxUSE_LIBHILDON2)
28 
29 void wxGetWorkAreaX11(Screen* screen, int& x, int& y, int& width, int& height);
30 
31 #ifndef __WXGTK3__
wx_gdk_screen_get_primary_monitor(GdkScreen * screen)32 static inline int wx_gdk_screen_get_primary_monitor(GdkScreen* screen)
33 {
34     int monitor = 0;
35 #if GTK_CHECK_VERSION(2,20,0)
36     if (gtk_check_version(2,20,0) == NULL)
37         monitor = gdk_screen_get_primary_monitor(screen);
38 #endif
39     return monitor;
40 }
41 #define gdk_screen_get_primary_monitor wx_gdk_screen_get_primary_monitor
42 #endif // !__WXGTK3__
43 
44 static inline void
wx_gdk_screen_get_monitor_workarea(GdkScreen * screen,int monitor,GdkRectangle * dest)45 wx_gdk_screen_get_monitor_workarea(GdkScreen* screen, int monitor, GdkRectangle* dest)
46 {
47 #if GTK_CHECK_VERSION(3,4,0)
48     if (gtk_check_version(3,4,0) == NULL)
49         gdk_screen_get_monitor_workarea(screen, monitor, dest);
50     else
51 #endif
52     {
53         gdk_screen_get_monitor_geometry(screen, monitor, dest);
54 #ifdef GDK_WINDOWING_X11
55 #ifdef __WXGTK3__
56         if (GDK_IS_X11_SCREEN(screen))
57 #endif
58         {
59             GdkRectangle rect = { 0 };
60             wxGetWorkAreaX11(GDK_SCREEN_XSCREEN(screen),
61                 rect.x, rect.y, rect.width, rect.height);
62             // in case _NET_WORKAREA result is too large
63             if (rect.width && rect.height)
64                 gdk_rectangle_intersect(dest, &rect, dest);
65         }
66 #endif // GDK_WINDOWING_X11
67     }
68 }
69 #define gdk_screen_get_monitor_workarea wx_gdk_screen_get_monitor_workarea
70 
71 #endif // !(wxUSE_LIBHILDON || wxUSE_LIBHILDON2)
72 
wxClientDisplayRect(int * x,int * y,int * width,int * height)73 void wxClientDisplayRect(int* x, int* y, int* width, int* height)
74 {
75 #if wxUSE_LIBHILDON || wxUSE_LIBHILDON2
76     GdkRectangle rect = { 0, 0, 672, 396 };
77 #else
78     GdkRectangle rect;
79     GdkWindow* window = gtk_widget_get_window(wxGetRootWindow());
80     GdkScreen* screen = gdk_window_get_screen(window);
81     int monitor = gdk_screen_get_monitor_at_window(screen, window);
82     gdk_screen_get_monitor_workarea(screen, monitor, &rect);
83 #endif
84     if (x)
85         *x = rect.x;
86     if (y)
87         *y = rect.y;
88     if (width)
89         *width = rect.width;
90     if (height)
91         *height = rect.height;
92 }
93 //-----------------------------------------------------------------------------
94 
95 #if wxUSE_DISPLAY
96 class wxDisplayFactoryGTK: public wxDisplayFactory
97 {
98 public:
99     virtual wxDisplayImpl* CreateDisplay(unsigned n);
100     virtual unsigned GetCount();
101     virtual int GetFromPoint(const wxPoint& pt);
102 };
103 
104 class wxDisplayImplGTK: public wxDisplayImpl
105 {
106     typedef wxDisplayImpl base_type;
107 public:
108     wxDisplayImplGTK(unsigned i);
109     virtual wxRect GetGeometry() const;
110     virtual wxRect GetClientArea() const;
111     virtual wxString GetName() const;
112     virtual bool IsPrimary() const;
113     virtual wxArrayVideoModes GetModes(const wxVideoMode& mode) const;
114     virtual wxVideoMode GetCurrentMode() const;
115     virtual bool ChangeMode(const wxVideoMode& mode);
116 
117     GdkScreen* const m_screen;
118 };
119 
GetScreen()120 static inline GdkScreen* GetScreen()
121 {
122     return gtk_widget_get_screen(wxGetRootWindow());
123 }
124 //-----------------------------------------------------------------------------
125 
CreateDisplay(unsigned n)126 wxDisplayImpl* wxDisplayFactoryGTK::CreateDisplay(unsigned n)
127 {
128     return new wxDisplayImplGTK(n);
129 }
130 
GetCount()131 unsigned wxDisplayFactoryGTK::GetCount()
132 {
133     return gdk_screen_get_n_monitors(GetScreen());
134 }
135 
GetFromPoint(const wxPoint & pt)136 int wxDisplayFactoryGTK::GetFromPoint(const wxPoint& pt)
137 {
138     GdkScreen* screen = GetScreen();
139     int monitor = gdk_screen_get_monitor_at_point(screen, pt.x, pt.y);
140     GdkRectangle rect;
141     gdk_screen_get_monitor_geometry(screen, monitor, &rect);
142     if (!wxRect(rect.x, rect.y, rect.width, rect.height).Contains(pt))
143         monitor = wxNOT_FOUND;
144     return monitor;
145 }
146 //-----------------------------------------------------------------------------
147 
wxDisplayImplGTK(unsigned i)148 wxDisplayImplGTK::wxDisplayImplGTK(unsigned i)
149     : base_type(i)
150     , m_screen(GetScreen())
151 {
152 }
153 
GetGeometry() const154 wxRect wxDisplayImplGTK::GetGeometry() const
155 {
156     GdkRectangle rect;
157     gdk_screen_get_monitor_geometry(m_screen, m_index, &rect);
158     return wxRect(rect.x, rect.y, rect.width, rect.height);
159 }
160 
GetClientArea() const161 wxRect wxDisplayImplGTK::GetClientArea() const
162 {
163     GdkRectangle rect;
164     gdk_screen_get_monitor_workarea(m_screen, m_index, &rect);
165     return wxRect(rect.x, rect.y, rect.width, rect.height);
166 }
167 
GetName() const168 wxString wxDisplayImplGTK::GetName() const
169 {
170     return wxString();
171 }
172 
IsPrimary() const173 bool wxDisplayImplGTK::IsPrimary() const
174 {
175     return gdk_screen_get_primary_monitor(m_screen) == int(m_index);
176 }
177 
178 wxArrayVideoModes wxXF86VidMode_GetModes(const wxVideoMode& mode, Display* pDisplay, int nScreen);
179 wxVideoMode wxXF86VidMode_GetCurrentMode(Display* display, int nScreen);
180 bool wxXF86VidMode_ChangeMode(const wxVideoMode& mode, Display* display, int nScreen);
181 wxArrayVideoModes wxX11_GetModes(const wxDisplayImpl* impl, const wxVideoMode& modeMatch, Display* display);
182 
GetModes(const wxVideoMode & mode) const183 wxArrayVideoModes wxDisplayImplGTK::GetModes(const wxVideoMode& mode) const
184 {
185     wxArrayVideoModes modes;
186 #ifdef GDK_WINDOWING_X11
187 #ifdef __WXGTK3__
188     if (GDK_IS_X11_SCREEN(m_screen))
189 #endif
190     {
191         Display* display = GDK_DISPLAY_XDISPLAY(gdk_screen_get_display(m_screen));
192 #ifdef HAVE_X11_EXTENSIONS_XF86VMODE_H
193         int nScreen = gdk_x11_screen_get_screen_number(m_screen);
194         modes = wxXF86VidMode_GetModes(mode, display, nScreen);
195 #else
196         modes = wxX11_GetModes(this, mode, display);
197 #endif
198     }
199 #endif // GDK_WINDOWING_X11
200     return modes;
201 }
202 
GetCurrentMode() const203 wxVideoMode wxDisplayImplGTK::GetCurrentMode() const
204 {
205     wxVideoMode mode;
206 #if defined(GDK_WINDOWING_X11) && defined(HAVE_X11_EXTENSIONS_XF86VMODE_H)
207 #ifdef __WXGTK3__
208     if (GDK_IS_X11_SCREEN(m_screen))
209 #endif
210     {
211         Display* display = GDK_DISPLAY_XDISPLAY(gdk_screen_get_display(m_screen));
212         int nScreen = gdk_x11_screen_get_screen_number(m_screen);
213         mode = wxXF86VidMode_GetCurrentMode(display, nScreen);
214     }
215 #endif
216     return mode;
217 }
218 
ChangeMode(const wxVideoMode & mode)219 bool wxDisplayImplGTK::ChangeMode(const wxVideoMode& mode)
220 {
221     bool success = false;
222 #if defined(GDK_WINDOWING_X11) && defined(HAVE_X11_EXTENSIONS_XF86VMODE_H)
223 #ifdef __WXGTK3__
224     if (GDK_IS_X11_SCREEN(m_screen))
225 #endif
226     {
227         Display* display = GDK_DISPLAY_XDISPLAY(gdk_screen_get_display(m_screen));
228         int nScreen = gdk_x11_screen_get_screen_number(m_screen);
229         success = wxXF86VidMode_ChangeMode(mode, display, nScreen);
230     }
231 #else
232     wxUnusedVar(mode);
233 #endif
234     return success;
235 }
236 
CreateFactory()237 wxDisplayFactory* wxDisplay::CreateFactory()
238 {
239     return new wxDisplayFactoryGTK;
240 }
241 #endif // wxUSE_DISPLAY
242