1 /* vi:set sw=2 sts=2 ts=2 et ai tw=100: */
2 /*-
3  * Copyright (c) 2017 Viktor Odintsev <zakhams@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or (at
8  * your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., Inc., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  */
20 
21 #include <string.h>
22 #include <gdk/gdkx.h>
23 
24 #include "xfwm-common.h"
25 #define DEFAULT_REFRESH_RATE 30
26 
27 
28 void
xfwm_widget_reparent(GtkWidget * widget,GtkWidget * new_parent)29 xfwm_widget_reparent (GtkWidget *widget,
30                       GtkWidget *new_parent)
31 {
32   GtkWidget *old_parent;
33 
34   g_return_if_fail (GTK_IS_WIDGET (widget));
35   g_return_if_fail (GTK_IS_CONTAINER (new_parent));
36 
37   old_parent = gtk_widget_get_parent (widget);
38 
39   g_return_if_fail (old_parent != NULL);
40 
41   if (old_parent != new_parent)
42     {
43       g_object_ref (widget);
44       gtk_container_remove (GTK_CONTAINER (old_parent), widget);
45       gtk_container_add (GTK_CONTAINER (new_parent), widget);
46       g_object_unref (widget);
47     }
48 }
49 
50 
51 
52 void
xfwm_get_screen_dimensions(gint * width,gint * height)53 xfwm_get_screen_dimensions (gint *width, gint *height)
54 {
55   GdkDisplay   *display;
56   GdkMonitor   *monitor;
57   GdkRectangle  geometry;
58 
59   display = gdk_display_get_default ();
60   monitor = gdk_display_get_primary_monitor (display);
61   gdk_monitor_get_geometry (monitor, &geometry);
62 
63   if (width != NULL)
64     *width = geometry.width;
65   if (height != NULL)
66     *height = geometry.height;
67 }
68 
69 
70 
71 static void
xfwm_geometry_convert_to_device_pixels(GdkRectangle * geometry,gint scale)72 xfwm_geometry_convert_to_device_pixels (GdkRectangle *geometry,
73                                         gint          scale)
74 {
75   if (geometry != NULL)
76     {
77       geometry->x *= scale;
78       geometry->y *= scale;
79       geometry->width *= scale;
80       geometry->height *= scale;
81     }
82 }
83 
84 
85 
86 void
xfwm_get_monitor_geometry(GdkScreen * screen,gint monitor_num,GdkRectangle * geometry,gboolean scaled)87 xfwm_get_monitor_geometry (GdkScreen    *screen,
88                            gint          monitor_num,
89                            GdkRectangle *geometry,
90                            gboolean      scaled)
91 {
92   gint        scale;
93   GdkDisplay *display;
94   GdkMonitor *monitor;
95 
96   display = gdk_screen_get_display (screen);
97   monitor = gdk_display_get_monitor (display, monitor_num);
98   scale = gdk_monitor_get_scale_factor (monitor);
99   gdk_monitor_get_geometry (monitor, geometry);
100 
101   if (scaled && scale != 1)
102     xfwm_geometry_convert_to_device_pixels (geometry, scale);
103 }
104 
105 
106 
107 gboolean
xfwm_get_primary_monitor_geometry(GdkScreen * screen,GdkRectangle * geometry,gboolean scaled)108 xfwm_get_primary_monitor_geometry (GdkScreen    *screen,
109                                    GdkRectangle *geometry,
110                                    gboolean      scaled)
111 {
112   gint        scale;
113   GdkDisplay *display;
114   GdkMonitor *monitor;
115 
116   display = gdk_screen_get_display (screen);
117   monitor = gdk_display_get_primary_monitor (display);
118 
119   if (!monitor)
120   {
121       geometry->width = 0;
122       geometry->height = 0;
123 
124       return FALSE;
125   }
126 
127   scale = gdk_monitor_get_scale_factor (monitor);
128   gdk_monitor_get_geometry (monitor, geometry);
129 
130   if (scaled && scale != 1)
131     xfwm_geometry_convert_to_device_pixels (geometry, scale);
132 
133   return TRUE;
134 }
135 
136 
137 
138 gint
xfwm_get_primary_refresh_rate(GdkScreen * screen)139 xfwm_get_primary_refresh_rate (GdkScreen *screen)
140 {
141   GdkDisplay *display;
142   GdkMonitor *monitor;
143   int         refresh_rate;
144 
145   display = gdk_screen_get_display (screen);
146   monitor = gdk_display_get_primary_monitor (display);
147   refresh_rate = 0;
148 
149   if (monitor)
150     refresh_rate = gdk_monitor_get_refresh_rate (monitor) / 1000;
151 
152   if (refresh_rate)
153     return refresh_rate;
154 
155   return DEFAULT_REFRESH_RATE;
156 }
157 
158 
159 
160 gboolean
xfwm_monitor_is_primary(GdkScreen * screen,gint monitor_num)161 xfwm_monitor_is_primary (GdkScreen *screen,
162                          gint      monitor_num)
163 {
164   GdkDisplay *display;
165   GdkMonitor *monitor;
166 
167   display = gdk_screen_get_display (screen);
168   monitor = gdk_display_get_monitor (display, monitor_num);
169 
170   return gdk_monitor_is_primary (monitor);
171 }
172 
173 
174 
175 gint
xfwm_get_n_monitors(GdkScreen * screen)176 xfwm_get_n_monitors (GdkScreen *screen)
177 {
178   return gdk_display_get_n_monitors (gdk_screen_get_display (screen));
179 }
180 
181 
182 
183 static gchar *
substitute_screen_number(const gchar * display_name,gint screen_number)184 substitute_screen_number (const gchar *display_name,
185                           gint         screen_number)
186 {
187   GString *str;
188   gchar   *p;
189 
190   str = g_string_new (display_name);
191 
192   p = strrchr (str->str, '.');
193   if (p != NULL && p > strchr (str->str, ':'))
194     {
195       /* remove screen number from string */
196       g_string_truncate (str, p - str->str);
197     }
198 
199   g_string_append_printf (str, ".%d", screen_number);
200 
201   return g_string_free (str, FALSE);
202 }
203 
204 
205 
206 gchar *
xfwm_make_display_name(GdkScreen * screen)207 xfwm_make_display_name (GdkScreen *screen)
208 {
209   const gchar *name;
210   gint         number;
211 
212   name = gdk_display_get_name (gdk_screen_get_display (screen));
213   number = gdk_x11_screen_get_screen_number (screen);
214 
215   return substitute_screen_number (name, number);
216 }
217