GTK+2 panel 

GTK+2 panel Git Source Tree

Root/libgpwidgets/gpw-panel.c

1/* Gtk2Panel - A bleeding edge Gtk+2 panel
2 * Copyright (C) 2009 Nicola Fontana <ntd at entidi.it>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20
21/**
22 * SECTION:gpw-panel
23 * @title: GpwPanel
24 * @short_description: A wanna-be panel based on #GtkWindow
25 *
26 * A GtkWindow widget that tries to be as panel as possible.
27 **/
28
29/**
30 * GpwPanel:
31 *
32 * All fields are private and should not be used directly.
33 * Use its public methods instead.
34 **/
35
36
37#include "gpw-panel.h"
38#include "gpw-panel-private.h"
39#include "gpw-intl.h"
40
41#include <X11/Xlib.h>
42#include <X11/Xatom.h>
43#include <gdk/gdkx.h>
44
45#define WIDGET_CLASS ((GtkWidgetClass *) gpw_panel_parent_class)
46
47
48enum {
49 PROP_0,
50 PROP_EDGE
51};
52
53
54static void get_property (GObject *object,
55 guint prop_id,
56 GValue *value,
57 GParamSpec *pspec);
58static void set_property (GObject *object,
59 guint prop_id,
60 const GValue *value,
61 GParamSpec *pspec);
62static void size_allocate (GtkWidget *widget,
63 GtkAllocation *allocation);
64static void realize (GtkWidget *widget);
65static void show (GtkWidget *widget);
66
67
68G_DEFINE_TYPE(GpwPanel, gpw_panel, GTK_TYPE_WINDOW);
69
70
71static void
72gpw_panel_class_init(GpwPanelClass *klass)
73{
74 GObjectClass *gobject_class;
75 GtkWidgetClass *widget_class;
76 GParamSpec *param;
77
78 gobject_class = (GObjectClass *) klass;
79 widget_class = (GtkWidgetClass *) klass;
80
81 g_type_class_add_private(klass, sizeof(GpwPanelPrivate));
82
83 gobject_class->get_property = get_property;
84 gobject_class->set_property = set_property;
85
86 widget_class->size_allocate = size_allocate;
87 widget_class->realize = realize;
88 widget_class->show = show;
89
90 param = g_param_spec_enum("edge",
91 P_("Edge"),
92 P_("Edge where this panel should be attached"),
93 GPW_TYPE_EDGE,
94 GPW_EDGE_TOP,
95 G_PARAM_CONSTRUCT|G_PARAM_READWRITE);
96 g_object_class_install_property(gobject_class, PROP_EDGE, param);
97}
98
99static void
100gpw_panel_init(GpwPanel *panel)
101{
102 GtkWindow *window;
103 GpwPanelPrivate *data;
104
105 window = (GtkWindow *) panel;
106 data = G_TYPE_INSTANCE_GET_PRIVATE(panel, GPW_TYPE_PANEL, GpwPanelPrivate);
107
108 data->edge = GPW_EDGE_TOP;
109
110 panel->data = data;
111
112 gtk_window_set_type_hint(window, GDK_WINDOW_TYPE_HINT_DOCK);
113 gtk_window_set_decorated(window, FALSE);
114 gtk_window_set_skip_taskbar_hint(window, TRUE);
115 gtk_window_set_skip_pager_hint(window, TRUE);
116 gtk_window_stick(window);
117 gtk_window_set_keep_above(window, TRUE);
118 gtk_window_set_keep_below(window, FALSE);
119 gtk_window_set_deletable(window, FALSE);
120}
121
122static void
123get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
124{
125 GpwPanelPrivate *data = GPW_PANEL_GET_DATA(object);
126
127 switch (prop_id) {
128 case PROP_EDGE:
129 g_value_set_enum(value, data->edge);
130 break;
131 default:
132 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
133 break;
134 }
135}
136
137static void
138set_property(GObject *object,
139 guint prop_id, const GValue *value, GParamSpec *pspec)
140{
141 GpwPanelPrivate *data = GPW_PANEL_GET_DATA(object);
142
143 switch (prop_id) {
144 case PROP_EDGE:
145 data->edge = g_value_get_enum(value);
146 break;
147 default:
148 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
149 break;
150 }
151}
152
153static void
154show(GtkWidget *widget)
155{
156 GtkWindow *window;
157 GtkWidget *child;
158 GtkRequisition requisition;
159 GdkGeometry hints;
160
161 window = (GtkWindow *) widget;
162 child = gtk_bin_get_child((GtkBin *) widget);
163
164 /* Empty panels are not allowed */
165 g_assert(child != NULL);
166
167 gtk_widget_show_all(child);
168
169 /* Check for height explicitely defined for the panel */
170 gtk_widget_get_size_request(widget,
171 &requisition.width, &requisition.height);
172
173 if (requisition.height <= 0) {
174 /* Height not explicitely defined: use the child height */
175 gint border = gtk_container_get_border_width((GtkContainer *) widget);
176
177 gtk_widget_size_request(child, &requisition);
178 requisition.height += border * 2;
179 }
180
181 requisition.width = gdk_screen_width();
182
183 /* Try to impose the requested size to the panel */
184 hints.min_width = hints.max_width = requisition.width;
185 hints.min_height = hints.max_height = requisition.height;
186 gtk_window_set_geometry_hints(window, widget, &hints,
187 GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
188 gtk_window_set_resizable(window, FALSE);
189
190 WIDGET_CLASS->show(widget);
191}
192
193static void
194size_allocate(GtkWidget *widget, GtkAllocation *allocation)
195{
196 GpwPanelPrivate *data = GPW_PANEL_GET_DATA(widget);
197
198 WIDGET_CLASS->size_allocate(widget, allocation);
199
200 data->allocation = *allocation;
201}
202
203static void
204realize(GtkWidget *widget)
205{
206 GtkWindow *window;
207 GpwPanelPrivate *data;
208 GdkWindow *gdk_window;
209 GtkAllocation *allocation;
210 Window handle;
211 Display *display;
212 Atom strut, strut_partial;
213 long value[12] = { 0 };
214
215 WIDGET_CLASS->realize(widget);
216
217 window = (GtkWindow *) widget;
218 data = GPW_PANEL_GET_DATA(widget);
219 gdk_window = gtk_widget_get_window(widget);
220 allocation = &data->allocation;
221 handle = GDK_WINDOW_XID(gdk_window);
222 display = GDK_WINDOW_XDISPLAY(gdk_window);
223 strut = XInternAtom(display, "_NET_WM_STRUT", FALSE);
224 strut_partial = XInternAtom(display, "_NET_WM_STRUT_PARTIAL", FALSE);
225
226 switch (data->edge) {
227
228 case GPW_EDGE_TOP:
229gtk_window_move(window, 0, 0);
230value[2] = allocation->height;
231value[8] = 0;
232value[9] = allocation->width;
233break;
234
235 case GPW_EDGE_BOTTOM:
236gtk_window_move(window, 0, gdk_screen_height() - allocation->height);
237value[3] = allocation->height;
238value[10] = 0;
239value[11] = allocation->width;
240break;
241
242 default:
243g_assert_not_reached();
244 }
245
246 /* Set strut and strut_partial */
247 XChangeProperty(display, handle, strut, XA_CARDINAL, 32,
248 PropModeReplace, (unsigned char *) value, 4);
249 XChangeProperty(display, handle, strut_partial, XA_CARDINAL, 32,
250 PropModeReplace, (unsigned char *) value, 12);
251}

Archive Download this file

Branches

Tags