1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 
3 /* Metacity 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 Street - Suite 500, Boston, MA
21  * 02110-1335, USA.
22  */
23 
24 #include <config.h>
25 #include "resizepopup.h"
26 #include "util-private.h"
27 #include <gtk/gtk.h>
28 #include <gdk/gdkx.h>
29 
30 struct _MetaResizePopup
31 {
32   GtkWidget *size_window;
33   GtkWidget *size_label;
34   Display *display;
35   int screen_number;
36 
37   int vertical_size;
38   int horizontal_size;
39 
40   gboolean showing;
41 
42   MetaRectangle rect;
43 };
44 
45 LOCAL_SYMBOL MetaResizePopup*
meta_ui_resize_popup_new(Display * display,int screen_number)46 meta_ui_resize_popup_new (Display *display,
47                           int      screen_number)
48 {
49   MetaResizePopup *popup;
50 
51   popup = g_new0 (MetaResizePopup, 1);
52 
53   popup->display = display;
54   popup->screen_number = screen_number;
55 
56   return popup;
57 }
58 
59 LOCAL_SYMBOL void
meta_ui_resize_popup_free(MetaResizePopup * popup)60 meta_ui_resize_popup_free (MetaResizePopup *popup)
61 {
62   g_return_if_fail (popup != NULL);
63 
64   if (popup->size_window)
65     gtk_widget_destroy (popup->size_window);
66 
67   free (popup);
68 }
69 
70 static void
ensure_size_window(MetaResizePopup * popup)71 ensure_size_window (MetaResizePopup *popup)
72 {
73   GtkWidget *frame;
74 
75   if (popup->size_window)
76     return;
77 
78   popup->size_window = gtk_window_new (GTK_WINDOW_POPUP);
79 
80   gtk_window_set_screen (GTK_WINDOW (popup->size_window),
81 			 gdk_display_get_screen (gdk_x11_lookup_xdisplay (popup->display),
82 						 popup->screen_number));
83 
84   /* never shrink the size window */
85   gtk_window_set_resizable (GTK_WINDOW (popup->size_window),
86                             TRUE);
87 
88   frame = gtk_frame_new (NULL);
89   gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
90 
91   gtk_container_add (GTK_CONTAINER (popup->size_window), frame);
92 
93   popup->size_label = gtk_label_new ("");
94   gtk_misc_set_padding (GTK_MISC (popup->size_label), 3, 3);
95 
96   gtk_container_add (GTK_CONTAINER (frame), popup->size_label);
97 
98   gtk_widget_show_all (frame);
99 }
100 
101 static void
update_size_window(MetaResizePopup * popup)102 update_size_window (MetaResizePopup *popup)
103 {
104   char *str;
105   int x, y;
106   int width, height;
107 
108   g_return_if_fail (popup->size_window != NULL);
109 
110   /* Translators: This represents the size of a window.  The first number is
111    * the width of the window and the second is the height.
112    */
113   str = g_strdup_printf (_("%d x %d"),
114                          popup->horizontal_size,
115                          popup->vertical_size);
116 
117   gtk_label_set_text (GTK_LABEL (popup->size_label), str);
118 
119   free (str);
120 
121   gtk_window_get_size (GTK_WINDOW (popup->size_window), &width, &height);
122 
123   x = popup->rect.x + (popup->rect.width - width) / 2;
124   y = popup->rect.y + (popup->rect.height - height) / 2;
125 
126   if (gtk_widget_get_realized (popup->size_window))
127     {
128       /* using move_resize to avoid jumpiness */
129       gdk_window_move_resize (gtk_widget_get_window (popup->size_window),
130                               x, y,
131                               width, height);
132     }
133   else
134     {
135       gtk_window_move   (GTK_WINDOW (popup->size_window),
136                          x, y);
137     }
138 }
139 
140 static void
sync_showing(MetaResizePopup * popup)141 sync_showing (MetaResizePopup *popup)
142 {
143   if (popup->showing)
144     {
145       if (popup->size_window)
146         gtk_widget_show (popup->size_window);
147 
148       if (popup->size_window && gtk_widget_get_realized (popup->size_window))
149         gdk_window_raise (gtk_widget_get_window (popup->size_window));
150     }
151   else
152     {
153       if (popup->size_window)
154         gtk_widget_hide (popup->size_window);
155     }
156 }
157 
158 LOCAL_SYMBOL void
meta_ui_resize_popup_set(MetaResizePopup * popup,MetaRectangle rect,int base_width,int base_height,int width_inc,int height_inc)159 meta_ui_resize_popup_set (MetaResizePopup *popup,
160                           MetaRectangle    rect,
161                           int              base_width,
162                           int              base_height,
163                           int              width_inc,
164                           int              height_inc)
165 {
166   gboolean need_update_size;
167   int display_w, display_h;
168 
169   g_return_if_fail (popup != NULL);
170 
171   need_update_size = FALSE;
172 
173   display_w = rect.width - base_width;
174   if (width_inc > 0)
175     display_w /= width_inc;
176 
177   display_h = rect.height - base_height;
178   if (height_inc > 0)
179     display_h /= height_inc;
180 
181   if (!meta_rectangle_equal(&popup->rect, &rect) ||
182       display_w != popup->horizontal_size ||
183       display_h != popup->vertical_size)
184     need_update_size = TRUE;
185 
186   popup->rect = rect;
187   popup->vertical_size = display_h;
188   popup->horizontal_size = display_w;
189 
190   if (need_update_size)
191     {
192       ensure_size_window (popup);
193       update_size_window (popup);
194     }
195 
196   sync_showing (popup);
197 }
198 
199 LOCAL_SYMBOL void
meta_ui_resize_popup_set_showing(MetaResizePopup * popup,gboolean showing)200 meta_ui_resize_popup_set_showing  (MetaResizePopup *popup,
201                                    gboolean         showing)
202 {
203   g_return_if_fail (popup != NULL);
204 
205   if (showing == popup->showing)
206     return;
207 
208   popup->showing = !!showing;
209 
210   if (popup->showing)
211     {
212       ensure_size_window (popup);
213       update_size_window (popup);
214     }
215 
216   sync_showing (popup);
217 }
218