1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 
3 /* Marco resizing-terminal-window feedback */
4 
5 /*
6  * Copyright (C) 2001 Havoc Pennington
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301, USA.
22  */
23 
24 #include <config.h>
25 #include <glib/gi18n-lib.h>
26 
27 #include "resizepopup.h"
28 #include "util.h"
29 #include <gtk/gtk.h>
30 #include <gdk/gdkx.h>
31 
32 struct _MetaResizePopup
33 {
34   GtkWidget *size_window;
35   GtkWidget *size_label;
36   Display *display;
37   int screen_number;
38 
39   int vertical_size;
40   int horizontal_size;
41 
42   gboolean showing;
43 
44   MetaRectangle rect;
45 };
46 
47 MetaResizePopup*
meta_ui_resize_popup_new(Display * display,int screen_number)48 meta_ui_resize_popup_new (Display *display,
49                           int      screen_number)
50 {
51   MetaResizePopup *popup;
52 
53   popup = g_new0 (MetaResizePopup, 1);
54 
55   popup->display = display;
56   popup->screen_number = screen_number;
57 
58   return popup;
59 }
60 
61 void
meta_ui_resize_popup_free(MetaResizePopup * popup)62 meta_ui_resize_popup_free (MetaResizePopup *popup)
63 {
64   g_return_if_fail (popup != NULL);
65 
66   if (popup->size_window)
67     gtk_widget_destroy (popup->size_window);
68 
69   g_free (popup);
70 }
71 
72 static void
ensure_size_window(MetaResizePopup * popup)73 ensure_size_window (MetaResizePopup *popup)
74 {
75   GtkWidget *frame;
76 
77   if (popup->size_window)
78     return;
79 
80   popup->size_window = gtk_window_new (GTK_WINDOW_POPUP);
81 
82   gtk_window_set_screen (GTK_WINDOW (popup->size_window),
83 			 gdk_display_get_default_screen (gdk_x11_lookup_xdisplay (popup->display)));
84 
85   /* never shrink the size window */
86   gtk_window_set_resizable (GTK_WINDOW (popup->size_window),
87                             TRUE);
88 
89   frame = gtk_frame_new (NULL);
90   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
91 
92   gtk_container_add (GTK_CONTAINER (popup->size_window), frame);
93 
94   popup->size_label = gtk_label_new ("");
95   gtk_widget_set_margin_start (popup->size_label, 3);
96   gtk_widget_set_margin_end (popup->size_label, 3);
97   gtk_widget_set_margin_top (popup->size_label, 3);
98   gtk_widget_set_margin_bottom (popup->size_label, 3);
99 
100   gtk_container_add (GTK_CONTAINER (frame), popup->size_label);
101 
102   gtk_widget_show_all (frame);
103 }
104 
105 static void
update_size_window(MetaResizePopup * popup)106 update_size_window (MetaResizePopup *popup)
107 {
108   char *str;
109   int x, y;
110   int width, height;
111   int scale;
112 
113   g_return_if_fail (popup->size_window != NULL);
114 
115   scale = gtk_widget_get_scale_factor (GTK_WIDGET (popup->size_window));
116   /* Translators: This represents the size of a window.  The first number is
117    * the width of the window and the second is the height.
118    */
119   str = g_strdup_printf (_("%d x %d"),
120                          popup->horizontal_size,
121                          popup->vertical_size);
122 
123   gtk_label_set_text (GTK_LABEL (popup->size_label), str);
124 
125   g_free (str);
126 
127   gtk_window_get_size (GTK_WINDOW (popup->size_window), &width, &height);
128 
129   x = popup->rect.x + (popup->rect.width - width) / 2;
130   y = popup->rect.y + (popup->rect.height - height) / 2;
131 
132   if (scale)
133     {
134       x = x / scale;
135       y = y / scale;
136     }
137 
138   if (gtk_widget_get_realized (popup->size_window))
139     {
140       /* using move_resize to avoid jumpiness */
141       gdk_window_move_resize (gtk_widget_get_window (popup->size_window),
142                               x, y,
143                               width, height);
144     }
145   else
146     {
147       gtk_window_move   (GTK_WINDOW (popup->size_window),
148                          x, y);
149     }
150 }
151 
152 static void
sync_showing(MetaResizePopup * popup)153 sync_showing (MetaResizePopup *popup)
154 {
155   if (popup->showing)
156     {
157       if (popup->size_window)
158         gtk_widget_show (popup->size_window);
159 
160       if (popup->size_window && gtk_widget_get_realized (popup->size_window))
161         gdk_window_raise (gtk_widget_get_window(GTK_WIDGET(popup->size_window)));
162     }
163   else
164     {
165       if (popup->size_window)
166         gtk_widget_hide (popup->size_window);
167     }
168 }
169 
170 void
meta_ui_resize_popup_set(MetaResizePopup * popup,MetaRectangle rect,int base_width,int base_height,int width_inc,int height_inc)171 meta_ui_resize_popup_set (MetaResizePopup *popup,
172                           MetaRectangle    rect,
173                           int              base_width,
174                           int              base_height,
175                           int              width_inc,
176                           int              height_inc)
177 {
178   gboolean need_update_size;
179   int display_w, display_h;
180 
181   g_return_if_fail (popup != NULL);
182 
183   need_update_size = FALSE;
184 
185   display_w = rect.width - base_width;
186   if (width_inc > 0)
187     display_w /= width_inc;
188 
189   display_h = rect.height - base_height;
190   if (height_inc > 0)
191     display_h /= height_inc;
192 
193   if (!meta_rectangle_equal(&popup->rect, &rect) ||
194       display_w != popup->horizontal_size ||
195       display_h != popup->vertical_size)
196     need_update_size = TRUE;
197 
198   popup->rect = rect;
199   popup->vertical_size = display_h;
200   popup->horizontal_size = display_w;
201 
202   if (need_update_size)
203     {
204       ensure_size_window (popup);
205       update_size_window (popup);
206     }
207 
208   sync_showing (popup);
209 }
210 
211 void
meta_ui_resize_popup_set_showing(MetaResizePopup * popup,gboolean showing)212 meta_ui_resize_popup_set_showing  (MetaResizePopup *popup,
213                                    gboolean         showing)
214 {
215   g_return_if_fail (popup != NULL);
216 
217   if (showing == popup->showing)
218     return;
219 
220   popup->showing = !!showing;
221 
222   if (popup->showing)
223     {
224       ensure_size_window (popup);
225       update_size_window (popup);
226     }
227 
228   sync_showing (popup);
229 }
230