l10n: Updated Russian (ru) translation to 100%
[maepad.git] / src / he / he-fullscreen-button.c
blobc413f92da3dd93f1cc8c646bca19c04e4eb45315
1 /*
2 * This file is a part of hildon-extras
4 * Copyright (C) 2009 Cornelius Hald <hald@icandy.de>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser Public License as published by
8 * the Free Software Foundation; version 2 of the license.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser Public License for more details.
17 /**
18 * SECTION:he-fullscreen-button
19 * @short_description: A semi-transparent button to leave fullscreen mode.
21 * #HeFullscreenButton is a semi transparent button which is automatically
22 * displayed whenever it's parent window enters fullscreen state.
23 * It's always displayed in the lower right corner of the parent window.
25 * The button is automatically hidden after 5 seconds of mouse click
26 * inactivity. If the user clicks the parent window the button is shown
27 * for another 5 second.
29 * If the user clicks the button, the "clicked" signal is emitted. If you did
30 * not provide a signal handler for the "clicked" signal, then the default
31 * handler will call gtk_window_unfullscreen() on the parent window.
32 * If you provide a signal handler, the default handler will not be called
33 * at all.
35 * So, if your application has just one window. It will be enough, if you create
36 * an instance of HeFullscreenButton with this window as parent. Now if your
37 * window switches to fullscreen the HeFullscreenButton is automatically shown
38 * and can be used to leave fullscreen mode. In this case you don't have to provide
39 * a signal handler and you don't have to take care of the buttons destruction.
42 #include <gtk/gtk.h>
43 #include <hildon/hildon.h>
44 #include <string.h>
45 #include "he-fullscreen-button.h"
47 #define FULLSCREEN_BUTTON_WIDTH 80
48 #define FULLSCREEN_BUTTON_HEIGHT 70
49 #define FULLSCREEN_BUTTON_HIDE_DELAY 5000
50 #define FULLSCREEN_BUTTON_CORNER_RADIUS 20
51 #define FULLSCREEN_BUTTON_ICON "general_fullsize"
52 #define FULLSCREEN_BUTTON_ICON_SIZE 48
53 #define OFFSET 0
55 typedef struct _HeFullscreenButtonPrivate HeFullscreenButtonPrivate;
57 struct _HeFullscreenButtonPrivate
59 gboolean release_event;
60 guint32 last_event_time;
62 guint button_press_signal_id;
63 guint button_release_signal_id;
65 gulong button_press_hook_id;
66 gulong button_release_hook_id;
68 gboolean act_on_state_change;
70 GtkWidget *overlay;
73 #define HE_FULLSCREEN_BUTTON_GET_PRIVATE(object) \
74 (G_TYPE_INSTANCE_GET_PRIVATE((object), \
75 HE_TYPE_FULLSCREEN_BUTTON, HeFullscreenButtonPrivate))
77 G_DEFINE_TYPE(HeFullscreenButton, he_fullscreen_button, G_TYPE_OBJECT)
80 /**
81 * Hides the fullscreen button.
83 static void
84 fullscreen_button_hide (HeFullscreenButton *self)
86 g_return_if_fail (HE_IS_FULLSCREEN_BUTTON (self));
88 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
89 g_return_if_fail (priv != NULL);
91 /* Reset timer */
92 g_source_remove_by_user_data ((gpointer) self);
94 if (priv->overlay != NULL && GTK_IS_WIDGET (priv->overlay)) {
95 gtk_widget_hide (priv->overlay);
101 * Changes the position of the fullscreen button.
103 static void
104 fullscreen_button_set_position (HeFullscreenButton *self)
106 GtkWidget *parent = GTK_WIDGET (self->parent_window);
107 GtkWidget *overlay = NULL;
109 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
110 g_return_if_fail (priv != NULL);
112 overlay = GTK_WIDGET (priv->overlay);
114 /* For some reason I have to call hide/show to make it appear at the new position */
115 gint x = parent->allocation.width - overlay->allocation.width;
116 gint y = parent->allocation.height - overlay->allocation.height - OFFSET;
118 gtk_widget_hide (overlay);
119 gtk_window_move (GTK_WINDOW (overlay), x, y);
120 gtk_widget_show (overlay);
125 * Everytime the timer runs out, we hide the fullscreen button.
127 static gboolean
128 fullscreen_button_on_hide_timer (gpointer data)
130 g_return_val_if_fail (data != NULL, FALSE);
131 fullscreen_button_hide (HE_FULLSCREEN_BUTTON (data));
132 return FALSE;
137 * Shows the full screen button.
139 static void
140 fullscreen_button_show (HeFullscreenButton *self)
142 g_return_if_fail (self != NULL);
144 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
145 g_return_if_fail (priv != NULL);
147 g_return_if_fail (GTK_IS_WIDGET (priv->overlay));
149 /* Stop return button hide timeout */
150 g_source_remove_by_user_data ((gpointer) self);
152 /* Only show overlay if we come here through a button release event, not a button press event */
153 if (priv->release_event) {
155 fullscreen_button_set_position (self);
156 gtk_widget_show (priv->overlay);
158 /* Set the return button hide timeout */
159 g_timeout_add (FULLSCREEN_BUTTON_HIDE_DELAY,
160 fullscreen_button_on_hide_timer, (gpointer) self);
166 * This hook function is called for each mouse button press or
167 * button release on the parent window.
169 static gboolean
170 fullscreen_button_input_activity_hook (GSignalInvocationHint *ihint G_GNUC_UNUSED,
171 guint n_param_values,
172 const GValue *param_values,
173 gpointer data)
175 HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (data);
176 g_return_val_if_fail (self, FALSE);
178 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
179 g_return_val_if_fail (priv != NULL, FALSE);
181 GdkEventAny *event = NULL;
183 if (n_param_values >= 2)
184 event = (GdkEventAny*) g_value_peek_pointer (&(param_values[1]));
186 g_return_val_if_fail (event, TRUE);
188 guint32 time = 0;
189 switch (event->type) {
190 case GDK_BUTTON_PRESS:
191 case GDK_BUTTON_RELEASE:
192 time = ((GdkEventButton*) event)->time;
193 break;
194 case GDK_KEY_PRESS:
195 case GDK_KEY_RELEASE:
196 time = ((GdkEventKey*) event)->time;
197 break;
198 default:
199 /* Filter out unexpected messages */
200 return TRUE;
203 /* We're likely to get events multiple times as they're propagated, so
204 filter out events that we've already seen. */
205 if (time == priv->last_event_time) {
206 return TRUE;
208 priv->last_event_time = time;
210 if (event && (event->type == GDK_BUTTON_PRESS)) {
211 priv->release_event = FALSE;
212 } else {
213 priv->release_event = TRUE;
216 fullscreen_button_show (self);
218 return TRUE;
223 * This function makes the full screen button visible and hooks mouse and
224 * key event signal emissions. The button is hidden after some time and
225 * is reshown when ever one of the signal hooks are activated.
227 * Note: The button may be shown automatically by itself
228 * if you have not set the act_on_state_change property to
229 * FALSE.
231 * @param self A HeFullscreenButton instance.
233 void
234 he_fullscreen_button_enable (HeFullscreenButton *self)
236 g_return_if_fail(HE_IS_FULLSCREEN_BUTTON(self));
238 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
239 g_return_if_fail (priv != NULL);
241 if (priv->button_press_hook_id == 0) {
242 priv->button_press_signal_id =
243 g_signal_lookup ("button-press-event", GTK_TYPE_WIDGET);
244 priv->button_press_hook_id =
245 g_signal_add_emission_hook (priv->button_press_signal_id, 0,
246 fullscreen_button_input_activity_hook,
247 (gpointer) self, NULL);
250 if (priv->button_release_hook_id == 0) {
251 priv->button_release_signal_id =
252 g_signal_lookup ("button-release-event", GTK_TYPE_WIDGET);
253 priv->button_release_hook_id =
254 g_signal_add_emission_hook (priv->button_release_signal_id, 0,
255 fullscreen_button_input_activity_hook,
256 (gpointer) self, NULL);
259 fullscreen_button_show(self);
264 * Hides the full screen button and releases mouse and
265 * key event signal emission hooks.
267 * Note: The button may be hidden automatically by itself
268 * if you have not set the act_on_state_change property to
269 * FALSE.
271 * @param self A HeFullscreenButton instance.
273 void
274 he_fullscreen_button_disable (HeFullscreenButton *self)
276 g_return_if_fail (HE_IS_FULLSCREEN_BUTTON (self));
278 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
279 g_return_if_fail (priv != NULL);
281 fullscreen_button_hide (self);
283 if (priv->button_release_hook_id > 0) {
284 g_signal_remove_emission_hook (priv->button_release_signal_id,
285 priv->button_release_hook_id);
286 priv->button_release_hook_id = 0;
289 if (priv->button_press_hook_id > 0) {
290 g_signal_remove_emission_hook (priv->button_press_signal_id,
291 priv->button_press_hook_id);
292 priv->button_press_hook_id = 0;
298 * Everytime the button is clicked, be emmit the "clicked" signal.
300 static gboolean
301 fullscreen_button_on_clicked (GtkWidget *widget, GdkEventButton *event G_GNUC_UNUSED, gpointer data)
303 HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (data);
304 g_signal_emit_by_name (self, "clicked");
306 return TRUE;
311 * Creates a rectangle with a rounded upper left corner.
313 static void
314 fullscreen_button_create_rectangle (cairo_t *ctx, double x, double y, double w, double h, double r)
316 cairo_move_to(ctx, x+r, y);
317 cairo_line_to(ctx, x+w, y);
318 cairo_line_to(ctx, x+w, y+h);
319 cairo_line_to(ctx, x, y+h);
320 cairo_line_to(ctx, x, y+r);
322 /* Left upper corner is rounded */
323 cairo_curve_to(ctx, x, y, x, y, x+r, y);
328 * Does the actuall drawing of the semi transparent button graphic.
330 static gboolean
331 fullscreen_button_on_expose_event (GtkWidget *widget, GdkEventExpose *event G_GNUC_UNUSED, gpointer data)
333 cairo_t *ctx;
334 GdkPixbuf *pixbuf = GDK_PIXBUF (data);
336 /* Create context */
337 ctx = gdk_cairo_create (widget->window);
339 /* Clear surface */
340 cairo_set_operator (ctx, CAIRO_OPERATOR_CLEAR);
341 cairo_paint (ctx);
343 /* Add rectangle */
344 cairo_set_operator (ctx, CAIRO_OPERATOR_OVER);
345 cairo_set_source_rgba (ctx, 0, 0, 0, 0.60);
346 fullscreen_button_create_rectangle (ctx, 0, 0, FULLSCREEN_BUTTON_WIDTH, FULLSCREEN_BUTTON_HEIGHT, FULLSCREEN_BUTTON_CORNER_RADIUS);
347 cairo_fill (ctx);
349 /* Add icon */
350 gdk_cairo_set_source_pixbuf (ctx, pixbuf, 15, 10);
351 cairo_paint (ctx);
353 /* Destroy context */
354 cairo_destroy (ctx);
355 return TRUE;
360 * Creates the semi transparent button graphic.
362 static GtkWidget*
363 fullscreen_button_create_gfx (HeFullscreenButton *self)
365 g_return_val_if_fail(HE_IS_FULLSCREEN_BUTTON(self), NULL);
367 GdkPixbuf *pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), FULLSCREEN_BUTTON_ICON, FULLSCREEN_BUTTON_ICON_SIZE, 0, NULL);
368 GtkWidget *img = gtk_image_new_from_pixbuf (pixbuf);
369 gtk_widget_show (img);
370 g_object_unref (pixbuf);
371 g_signal_connect (img, "expose_event", G_CALLBACK (fullscreen_button_on_expose_event), pixbuf);
373 GtkWidget *box = gtk_event_box_new ();
374 gtk_event_box_set_visible_window (GTK_EVENT_BOX(box), FALSE);
375 gtk_widget_show (box);
376 gtk_container_add (GTK_CONTAINER(box), img);
377 g_signal_connect (box, "button-release-event", G_CALLBACK (fullscreen_button_on_clicked), self);
379 GtkWidget *overlay = gtk_window_new (GTK_WINDOW_POPUP);
380 gtk_window_set_decorated (GTK_WINDOW (overlay), FALSE);
381 gtk_widget_set_size_request (overlay, FULLSCREEN_BUTTON_WIDTH, FULLSCREEN_BUTTON_HEIGHT);
382 gtk_window_set_resizable (GTK_WINDOW (overlay), FALSE);
383 gtk_window_set_transient_for (GTK_WINDOW (overlay), self->parent_window);
384 gtk_window_set_destroy_with_parent (GTK_WINDOW (overlay), TRUE);
385 gtk_container_add (GTK_CONTAINER (overlay), box);
387 GdkScreen *screen = gtk_widget_get_screen (overlay);
388 gtk_widget_set_colormap (overlay, gdk_screen_get_rgba_colormap (screen));
390 gtk_widget_realize (overlay);
392 return overlay;
396 * Called when the parent_window's is on the screen/not on the screen.
397 * Only called if parent_window is a HildonWindow (or derived from it).
399 * We check if the window is on the screen or not on the screen.
400 * If it is, and the window is in fullscreen mode, we enable the fullscreen button. If not, we disable the button.
402 static void
403 fullscreen_button_on_is_topmost_changed (GObject *object G_GNUC_UNUSED,
404 GParamSpec *property G_GNUC_UNUSED,
405 gpointer data)
407 HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (data);
409 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
410 g_return_if_fail (priv != NULL);
412 /* Only run if the "act-on-state-change" property is TRUE. */
413 if (!priv->act_on_state_change) {
414 return;
417 if (hildon_window_get_is_topmost (HILDON_WINDOW(self->parent_window))) {
418 if (gdk_window_get_state (GTK_WIDGET (self->parent_window)->window) & GDK_WINDOW_STATE_FULLSCREEN) {
419 he_fullscreen_button_enable (self);
422 else {
423 he_fullscreen_button_disable (self);
428 * Called, whenever the state of the parents window's GdkWindow changes.
429 * We check if the new state is fullscreen or non-fullscreen.
430 * If it is fullscreen, we enable the fullscreen button. If not, not.
432 static gboolean
433 fullscreen_button_on_window_state_changed (GtkWidget *widget G_GNUC_UNUSED,
434 GdkEventWindowState *event,
435 gpointer data)
437 HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (data);
439 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
440 g_return_val_if_fail (priv != NULL, FALSE);
442 /* Only run if the "act-on-state-change" property is TRUE. */
443 if (!priv->act_on_state_change) {
444 return FALSE;
447 /* Only run if this window is topmost. */
448 if (HILDON_IS_WINDOW (self->parent_window)) {
449 if (!hildon_window_get_is_topmost (HILDON_WINDOW(self->parent_window))) {
450 return FALSE;
454 if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
456 if (event->new_window_state == GDK_WINDOW_STATE_FULLSCREEN) {
457 he_fullscreen_button_enable (self);
458 } else {
459 he_fullscreen_button_disable (self);
464 return FALSE;
469 * Destroys the fullscreen button and disconnects itself from the parent window.
471 static void
472 fullscreen_button_destroy (GtkWidget *parent_window G_GNUC_UNUSED, HeFullscreenButton *self)
474 g_return_if_fail (self != NULL);
476 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
477 g_return_if_fail (priv != NULL);
479 if (self->parent_window != NULL) {
480 g_signal_handlers_disconnect_by_func (self->parent_window, fullscreen_button_destroy, self);
481 g_signal_handlers_disconnect_by_func (self->parent_window, fullscreen_button_on_window_state_changed, self);
482 if (HILDON_IS_WINDOW(parent_window)) {
483 g_signal_handlers_disconnect_by_func (self->parent_window, fullscreen_button_on_is_topmost_changed, self);
487 he_fullscreen_button_disable (self);
489 if (priv->overlay != NULL && GTK_IS_WIDGET(priv->overlay)) {
490 gtk_widget_destroy (GTK_WIDGET(priv->overlay));
491 priv->overlay = NULL;
497 * Called when the size allocation of the parent window changes.
498 * We change the position of the fullscreen button to always be in
499 * the lower right corner.
501 static void
502 fullscreen_button_on_parent_size_changed (GtkWidget *widget,
503 GtkAllocation *allocation,
504 gpointer user_data)
506 g_return_if_fail (widget != NULL);
507 g_return_if_fail (allocation != NULL);
509 HeFullscreenButton *self = HE_FULLSCREEN_BUTTON(user_data);
510 g_return_if_fail (self != NULL);
512 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
513 g_return_if_fail (priv != NULL);
515 GtkWidget *ui_win = GTK_WIDGET(priv->overlay);
516 g_return_if_fail (ui_win != NULL);
518 if (gdk_window_is_visible(priv->overlay->window)) {
519 fullscreen_button_set_position(self);
525 * Default handler for the "clicked" signal. If no user handler is
526 * defined we call gtk_window_unfullscreen() on the parent window.
527 * Otherwise only the user handler is executed.
529 static void
530 fullscreen_button_clicked_default_handler (HeFullscreenButton *self)
532 guint signal_id = g_signal_lookup ("clicked", HE_TYPE_FULLSCREEN_BUTTON);
533 gulong handler_id = g_signal_handler_find (self, G_SIGNAL_MATCH_ID, signal_id, 0, NULL, NULL, NULL);
535 /* Run only, if no signal handler is connected */
536 if (handler_id == 0) {
537 GtkWindow *window = he_fullscreen_button_get_window (self);
538 gtk_window_unfullscreen (window);
543 * Create new full screen button instance.
544 * This function attaches the full screen button to the given parent window.
545 * By default, the button automatically becomes visible if the parent window
546 * changes to fullscreen and vice versa. Change the "act-on-state-change"
547 * property to modify this behaviour.
549 * If you destroy the parent window, this HeFullscreenButton instance get
550 * destroyed as well.
552 * Pass it a HildonWindow (or one of its deriatives) to ensure the widget disables/
553 * enables itself on focus-out/focus-in respectively.
555 * @param parent_window A GtkWindow instance.
556 * @return New HeFullscreenButton instance.
558 HeFullscreenButton *
559 he_fullscreen_button_new (GtkWindow *parent_window)
561 g_return_val_if_fail (parent_window != NULL, NULL);
562 g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL);
564 HeFullscreenButton *self = g_object_new (HE_TYPE_FULLSCREEN_BUTTON, NULL);
566 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
567 g_return_val_if_fail (priv != NULL, NULL);
569 self->parent_window = parent_window;
570 priv->overlay = fullscreen_button_create_gfx (self);
572 g_signal_connect (parent_window, "destroy",
573 G_CALLBACK(fullscreen_button_destroy), self);
575 g_signal_connect (parent_window, "window-state-event",
576 G_CALLBACK(fullscreen_button_on_window_state_changed), self);
578 g_signal_connect_after (parent_window, "size-allocate",
579 G_CALLBACK(fullscreen_button_on_parent_size_changed), self);
581 if (HILDON_IS_WINDOW(parent_window)) {
582 g_signal_connect (parent_window, "notify::is-topmost",
583 G_CALLBACK(fullscreen_button_on_is_topmost_changed), self);
586 return self;
590 * Returns the GtkWidget displaying the actual overlaid button.
592 * @param self An instance of HeFullscreenButton
593 * @return The GtkWidget of the overlaid button. This widget belongs to HeFullscreenButton and must not be destroyed or modified.
595 GtkWidget *
596 he_fullscreen_button_get_overlay (HeFullscreenButton *self)
598 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
599 g_return_val_if_fail (priv != NULL, NULL);
601 return priv->overlay;
605 * Returns the GtkWindow that this HeFullscreenButton
606 * is attached to.
608 * @param self An instance of HeFullscreenButton
609 * @return The GtkWindow to which this button is attached to
611 GtkWindow *
612 he_fullscreen_button_get_window (HeFullscreenButton *self)
614 return self->parent_window;
619 * GObject stuff
622 enum {
623 CLICKED,
624 LAST_SIGNAL
627 static guint signals[LAST_SIGNAL] = {0};
629 enum {
630 PROP_0,
631 PROP_ACT_ON_STATE_CHANGE
634 static void
635 fullscreen_button_get_property (GObject *object,
636 guint property_id,
637 GValue *value,
638 GParamSpec * pspec)
640 HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (object);
641 g_return_if_fail (self);
643 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
644 g_return_if_fail (priv != NULL);
646 switch (property_id) {
647 case PROP_ACT_ON_STATE_CHANGE:
648 g_value_set_boolean (value, priv->act_on_state_change);
649 break;
651 default:
652 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
653 break;
657 static void
658 fullscreen_button_set_property (GObject *object,
659 guint property_id,
660 const GValue *value,
661 GParamSpec * pspec)
663 HeFullscreenButton *self = HE_FULLSCREEN_BUTTON (object);
664 g_return_if_fail (self);
666 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
667 g_return_if_fail (priv != NULL);
669 switch (property_id) {
670 case PROP_ACT_ON_STATE_CHANGE:
671 priv->act_on_state_change = g_value_get_boolean (value);
672 g_object_notify (G_OBJECT (object), "act-on-state-change");
673 break;
675 default:
676 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
677 break;
682 static void
683 he_fullscreen_button_class_init (HeFullscreenButtonClass *klass)
685 GObjectClass *object_class = G_OBJECT_CLASS (klass);
687 object_class->get_property = fullscreen_button_get_property;
688 object_class->set_property = fullscreen_button_set_property;
690 klass->clicked = fullscreen_button_clicked_default_handler;
693 * HeFullscreenButton::clicked
695 * Emitted when the #HeFullscreenButton was clicked by the user.
697 signals[CLICKED] =
698 g_signal_new(
699 "clicked",
700 HE_TYPE_FULLSCREEN_BUTTON,
701 G_SIGNAL_RUN_LAST,
702 G_STRUCT_OFFSET(HeFullscreenButtonClass, clicked),
703 NULL, NULL,
704 g_cclosure_marshal_VOID__VOID,
705 G_TYPE_NONE,
708 g_object_class_install_property(
709 object_class, PROP_ACT_ON_STATE_CHANGE,
710 g_param_spec_boolean ("act-on-state-change",
711 "Act on window state changes",
712 "Whether to automatically enable/disable the button "
713 "when its parent window fullscreens/unfullscreens "
714 "itself.",
715 TRUE,
716 G_PARAM_READWRITE));
718 g_type_class_add_private (klass, sizeof (HeFullscreenButtonPrivate));
722 static void
723 he_fullscreen_button_init (HeFullscreenButton *self)
725 g_return_if_fail (self != NULL);
727 HeFullscreenButtonPrivate *priv = HE_FULLSCREEN_BUTTON_GET_PRIVATE (self);
728 g_return_if_fail (priv != NULL);
730 memset (priv, 0, sizeof (HeFullscreenButtonPrivate));
732 self->parent_window = NULL;
733 priv->overlay = NULL;
734 priv->release_event = TRUE;
735 priv->last_event_time = 0;
737 priv->act_on_state_change = TRUE;
739 priv->button_press_signal_id = 0;
740 priv->button_release_signal_id = 0;
742 priv->button_press_hook_id = 0;
743 priv->button_release_hook_id = 0;