1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3
* panel-toplevel.c: The panel's toplevel window object.
5
* Copyright (C) 2003 Sun Microsystems, Inc.
6
* Copyright (C) 2004 Rob Adams
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.
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.
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., 59 Temple Place - Suite 330, Boston, MA
24
* Mark McLoughlin <mark@skynet.ie>
29
#include "panel-toplevel.h"
35
#include <gdk/gdkkeysyms.h>
36
#include <glib/gi18n.h>
38
#include <libpanel-util/panel-glib.h>
40
#include "panel-frame.h"
41
#include "panel-xutils.h"
42
#include "panel-multiscreen.h"
43
#include "panel-a11y.h"
44
#include "panel-typebuiltins.h"
45
#include "panel-marshal.h"
46
#include "panel-widget.h"
47
#include "panel-bindings.h"
48
#include "panel-struts.h"
49
#include "panel-lockdown.h"
50
#include "panel-schemas.h"
52
G_DEFINE_TYPE (PanelToplevel, panel_toplevel, GTK_TYPE_WINDOW)
54
#define PANEL_TOPLEVEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_TOPLEVEL, PanelToplevelPrivate))
56
#define DEFAULT_SIZE 48
57
#define DEFAULT_AUTO_HIDE_SIZE 1
58
#define DEFAULT_HIDE_DELAY 300
59
#define DEFAULT_UNHIDE_DELAY 100
60
#define DEFAULT_DND_THRESHOLD 8
61
#define MINIMUM_WIDTH 100
62
#define MAXIMUM_SIZE_SCREEN_RATIO 5
63
#define SNAP_TOLERANCE_FACTOR 6
64
#define DEFAULT_ARROW_SIZE 20
65
#define HANDLE_SIZE 10
71
PANEL_GRAB_OP_RESIZE_UP,
72
PANEL_GRAB_OP_RESIZE_DOWN,
73
PANEL_GRAB_OP_RESIZE_LEFT,
74
PANEL_GRAB_OP_RESIZE_RIGHT
77
struct _PanelToplevelPrivate {
82
GSettings *delayed_settings;
83
guint apply_delayed_id;
86
PanelOrientation orientation;
89
/* relative to the monitor origin */
92
/* relative to the bottom right corner, -1 to ignore and use x, y*/
97
/* this is used when the configured monitor is missing. We keep it so
98
* we can move the toplevel to the right monitor when it becomes
100
int configured_monitor;
105
PanelAnimationSpeed animation_speed;
108
GtkSettings *gtk_settings;
116
guint unhide_timeout;
118
GdkRectangle geometry;
119
PanelFrameEdge edges;
124
PanelGrabOpType grab_op;
126
/* The offset within the panel from which the panel
127
* drag was initiated relative to the screen origin.
132
/* Saved state before for cancelled grab op */
139
int orig_orientation;
141
/* relative to the monitor origin */
144
int animation_end_width;
145
int animation_end_height;
146
GTimeVal animation_start_time;
147
GTimeVal animation_end_time;
148
guint animation_timeout;
150
PanelWidget *panel_widget;
151
PanelFrame *inner_frame;
153
GtkWidget *hide_button_top;
154
GtkWidget *hide_button_bottom;
155
GtkWidget *hide_button_left;
156
GtkWidget *hide_button_right;
158
gint n_autohide_disablers;
162
guint buttons_enabled : 1;
163
guint arrows_enabled : 1;
165
/* The co-ordinates are relative to center screen */
166
guint x_centered : 1;
167
guint y_centered : 1;
169
/* The panel is not lined up with th screen edge */
172
/* We are currently animating a hide/show */
175
/* This is a keyboard initiated grab operation */
176
guint grab_is_keyboard : 1;
178
/* The x-y co-ordinates temporarily specify the panel center.
179
* This is used when the panel is rotating, because the width/height
180
* of the toplevel might change, so we need to compute new values for
182
guint position_centered : 1;
184
/* More saved grab op state */
185
guint orig_x_centered : 1;
186
guint orig_y_centered : 1;
188
/* flag to see if we have already done geometry updating,
189
if not then we're still loading and can ignore many things */
190
guint updated_geometry_initial : 1;
191
/* flag to see if we have done the initial animation */
192
guint initial_animation_done : 1;
198
POPUP_PANEL_MENU_SIGNAL,
199
TOGGLE_EXPAND_SIGNAL,
202
TOGGLE_HIDDEN_SIGNAL,
228
PROP_ANIMATION_SPEED,
229
PROP_BUTTONS_ENABLED,
233
static guint toplevel_signals [LAST_SIGNAL] = { 0 };
234
static GSList *toplevel_list = NULL;
236
static void panel_toplevel_calculate_animation_end_geometry (PanelToplevel *toplevel);
238
static gboolean panel_toplevel_position_is_writable (PanelToplevel *toplevel);
240
static void panel_toplevel_bind_gsettings (PanelToplevel *toplevel);
241
static void panel_toplevel_set_toplevel_id (PanelToplevel *toplevel,
242
const char *toplevel_id);
243
static void panel_toplevel_set_settings_path (PanelToplevel *toplevel,
244
const char *settings_path);
245
static void panel_toplevel_set_animate (PanelToplevel *toplevel,
248
static void panel_toplevel_update_monitor (PanelToplevel *toplevel);
249
static void panel_toplevel_set_monitor_internal (PanelToplevel *toplevel,
251
gboolean force_resize);
255
panel_toplevel_list_toplevels (void)
257
return toplevel_list;
261
panel_toplevel_get_by_id (const char *toplevel_id)
265
if (PANEL_GLIB_STR_EMPTY (toplevel_id))
268
for (l = toplevel_list; l; l = l->next) {
269
PanelToplevel *toplevel = l->data;
271
if (!g_strcmp0 (toplevel->priv->toplevel_id, toplevel_id))
279
panel_toplevel_is_last (PanelToplevel *toplevel)
283
for (l = toplevel_list; l; l = l->next) {
284
if (l->data != toplevel)
292
panel_toplevel_find_empty_spot (GdkScreen *screen,
293
PanelOrientation *orientation,
299
gboolean found_a_spot = FALSE;
302
*orientation = PANEL_ORIENTATION_TOP;
304
filled_spots = g_new0 (int, panel_multiscreen_monitors (screen));
306
for (li = panel_toplevel_list_toplevels (); li != NULL; li = li->next) {
307
PanelToplevel *toplevel = li->data;
308
GdkScreen *toplevel_screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
309
int toplevel_monitor = panel_toplevel_get_monitor (toplevel);
311
if (toplevel_screen != screen ||
312
toplevel_monitor < 0)
315
filled_spots[toplevel_monitor] |= panel_toplevel_get_orientation (toplevel);
318
for (i = 0; i < panel_multiscreen_monitors (screen); i++) {
319
/* These are ordered based on "priority" of the
320
orientation when picking it */
321
if ( ! (filled_spots[i] & PANEL_ORIENTATION_TOP)) {
322
*orientation = PANEL_ORIENTATION_TOP;
326
} else if ( ! (filled_spots[i] & PANEL_ORIENTATION_BOTTOM)) {
327
*orientation = PANEL_ORIENTATION_BOTTOM;
331
} else if ( ! (filled_spots[i] & PANEL_ORIENTATION_RIGHT)) {
332
*orientation = PANEL_ORIENTATION_RIGHT;
336
} else if ( ! (filled_spots[i] & PANEL_ORIENTATION_LEFT)) {
337
*orientation = PANEL_ORIENTATION_LEFT;
344
g_free (filled_spots);
350
panel_toplevel_get_screen_geometry (PanelToplevel *toplevel,
356
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), NULL);
357
g_return_val_if_fail (width != NULL && height != NULL, NULL);
359
screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
361
*width = gdk_screen_get_width (screen);
362
*height = gdk_screen_get_height (screen);
368
panel_toplevel_get_monitor_geometry (PanelToplevel *toplevel,
376
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), NULL);
377
g_return_val_if_fail (width != NULL && height != NULL, NULL);
379
screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
381
if (x) *x = panel_multiscreen_x (screen, toplevel->priv->monitor);
382
if (y) *y = panel_multiscreen_y (screen, toplevel->priv->monitor);
384
if (width) *width = panel_multiscreen_width (screen, toplevel->priv->monitor);
385
if (height) *height = panel_multiscreen_height (screen, toplevel->priv->monitor);
391
panel_toplevel_grab_op_cursor (PanelToplevel *toplevel,
392
PanelGrabOpType grab_op)
394
GdkCursorType retval = -1;
397
case PANEL_GRAB_OP_MOVE:
398
case PANEL_GRAB_OP_RESIZE:
399
if (toplevel->priv->grab_is_keyboard)
405
case PANEL_GRAB_OP_RESIZE_UP:
406
retval = GDK_TOP_SIDE;
408
case PANEL_GRAB_OP_RESIZE_DOWN:
409
retval = GDK_BOTTOM_SIDE;
411
case PANEL_GRAB_OP_RESIZE_LEFT:
412
retval = GDK_LEFT_SIDE;
414
case PANEL_GRAB_OP_RESIZE_RIGHT:
415
retval = GDK_RIGHT_SIDE;
418
g_assert_not_reached ();
426
panel_toplevel_init_resize_drag_offsets (PanelToplevel *toplevel,
427
PanelGrabOpType grab_op)
429
toplevel->priv->drag_offset_x = 0;
430
toplevel->priv->drag_offset_y = 0;
433
case PANEL_GRAB_OP_RESIZE_DOWN:
434
toplevel->priv->drag_offset_y = toplevel->priv->geometry.y;
436
case PANEL_GRAB_OP_RESIZE_UP:
437
toplevel->priv->drag_offset_y =
438
toplevel->priv->geometry.y + toplevel->priv->geometry.height;
440
case PANEL_GRAB_OP_RESIZE_RIGHT:
441
toplevel->priv->drag_offset_x = toplevel->priv->geometry.x;
443
case PANEL_GRAB_OP_RESIZE_LEFT:
444
toplevel->priv->drag_offset_x =
445
toplevel->priv->geometry.x + toplevel->priv->geometry.width;
448
g_assert_not_reached ();
454
panel_toplevel_warp_pointer (PanelToplevel *toplevel)
457
GdkRectangle geometry;
460
widget = GTK_WIDGET (toplevel);
462
geometry = toplevel->priv->geometry;
466
switch (toplevel->priv->grab_op) {
467
case PANEL_GRAB_OP_MOVE:
468
case PANEL_GRAB_OP_RESIZE:
469
x = (geometry.width / 2);
470
y = (geometry.height / 2);
472
case PANEL_GRAB_OP_RESIZE_UP:
473
x = (geometry.width / 2);
475
case PANEL_GRAB_OP_RESIZE_DOWN:
476
x = (geometry.width / 2);
479
case PANEL_GRAB_OP_RESIZE_LEFT:
480
y = (geometry.height / 2);
482
case PANEL_GRAB_OP_RESIZE_RIGHT:
484
y = (geometry.height / 2);
487
g_assert_not_reached ();
491
if (toplevel->priv->grab_op == PANEL_GRAB_OP_MOVE ||
492
toplevel->priv->grab_op == PANEL_GRAB_OP_RESIZE) {
493
toplevel->priv->drag_offset_x = x;
494
toplevel->priv->drag_offset_y = y;
496
panel_toplevel_init_resize_drag_offsets (toplevel, toplevel->priv->grab_op);
498
panel_warp_pointer (gtk_widget_get_window (widget), x, y);
502
panel_toplevel_begin_grab_op (PanelToplevel *toplevel,
503
PanelGrabOpType op_type,
504
gboolean grab_keyboard,
509
GdkCursorType cursor_type;
514
GdkDeviceManager *device_manager;
516
if (toplevel->priv->state != PANEL_STATE_NORMAL ||
517
toplevel->priv->grab_op != PANEL_GRAB_OP_NONE)
520
if (panel_lockdown_get_panels_locked_down_s ())
523
/* If any of the position/orientation are not writable,
524
then we can't really move freely */
525
if (op_type == PANEL_GRAB_OP_MOVE &&
526
!panel_toplevel_position_is_writable (toplevel))
529
/* If size is not writable, then we can't resize */
530
if ((op_type == PANEL_GRAB_OP_RESIZE ||
531
op_type == PANEL_GRAB_OP_RESIZE_UP ||
532
op_type == PANEL_GRAB_OP_RESIZE_DOWN ||
533
op_type == PANEL_GRAB_OP_RESIZE_LEFT ||
534
op_type == PANEL_GRAB_OP_RESIZE_RIGHT) &&
535
! g_settings_is_writable (toplevel->priv->settings,
536
PANEL_TOPLEVEL_SIZE_KEY))
539
widget = GTK_WIDGET (toplevel);
540
window = gtk_widget_get_window (widget);
542
toplevel->priv->grab_op = op_type;
543
toplevel->priv->grab_is_keyboard = grab_keyboard;
545
toplevel->priv->orig_monitor = toplevel->priv->monitor;
546
toplevel->priv->orig_x = toplevel->priv->x;
547
toplevel->priv->orig_x_right = toplevel->priv->x_right;
548
toplevel->priv->orig_x_centered = toplevel->priv->x_centered;
549
toplevel->priv->orig_y = toplevel->priv->y;
550
toplevel->priv->orig_y_bottom = toplevel->priv->y_bottom;
551
toplevel->priv->orig_y_centered = toplevel->priv->y_centered;
552
toplevel->priv->orig_size = toplevel->priv->size;
553
toplevel->priv->orig_orientation = toplevel->priv->orientation;
555
gtk_grab_add (widget);
557
if (toplevel->priv->grab_is_keyboard)
558
panel_toplevel_warp_pointer (toplevel);
560
cursor_type = panel_toplevel_grab_op_cursor (
561
toplevel, toplevel->priv->grab_op);
563
cursor = gdk_cursor_new (cursor_type);
565
display = gdk_window_get_display (window);
566
device_manager = gdk_display_get_device_manager (display);
567
pointer = gdk_device_manager_get_client_pointer (device_manager);
568
keyboard = gdk_device_get_associated_device (pointer);
570
gdk_device_grab (pointer, window,
571
GDK_OWNERSHIP_NONE, FALSE,
572
GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
575
g_object_unref (cursor);
578
gdk_device_grab (keyboard, window,
579
GDK_OWNERSHIP_NONE, FALSE,
580
GDK_KEY_PRESS | GDK_KEY_RELEASE,
585
panel_toplevel_end_grab_op (PanelToplevel *toplevel,
592
GdkDeviceManager *device_manager;
594
g_return_if_fail (toplevel->priv->grab_op != PANEL_GRAB_OP_NONE);
596
widget = GTK_WIDGET (toplevel);
598
toplevel->priv->grab_op = PANEL_GRAB_OP_NONE;
599
toplevel->priv->grab_is_keyboard = FALSE;
601
gtk_grab_remove (widget);
603
display = gtk_widget_get_display (widget);
604
device_manager = gdk_display_get_device_manager (display);
605
pointer = gdk_device_manager_get_client_pointer (device_manager);
606
keyboard = gdk_device_get_associated_device (pointer);
608
gdk_device_ungrab (pointer, time_);
609
gdk_device_ungrab (keyboard, time_);
613
panel_toplevel_cancel_grab_op (PanelToplevel *toplevel,
616
panel_toplevel_set_orientation (toplevel, toplevel->priv->orig_orientation);
617
panel_toplevel_set_monitor (toplevel, toplevel->priv->orig_monitor);
618
panel_toplevel_set_size (toplevel, toplevel->priv->orig_size);
619
panel_toplevel_set_x (toplevel,
620
toplevel->priv->orig_x,
621
toplevel->priv->orig_x_right,
622
toplevel->priv->orig_x_centered);
623
panel_toplevel_set_y (toplevel,
624
toplevel->priv->orig_y,
625
toplevel->priv->orig_y_bottom,
626
toplevel->priv->orig_y_centered);
630
panel_toplevel_resize_to_pointer (PanelToplevel *toplevel,
636
int new_x_right, new_y_bottom;
637
int new_x_centered, new_y_centered;
638
int monitor_width, monitor_height;
640
new_size = toplevel->priv->size;
641
new_x = toplevel->priv->x;
642
new_y = toplevel->priv->y;
643
new_x_right = toplevel->priv->x_right;
644
new_y_bottom = toplevel->priv->y_bottom;
645
new_x_centered = toplevel->priv->x_centered;
646
new_y_centered = toplevel->priv->y_centered;
648
panel_toplevel_get_monitor_geometry (toplevel, NULL, NULL, &monitor_width, &monitor_height);
650
switch (toplevel->priv->grab_op) {
651
case PANEL_GRAB_OP_RESIZE_UP:
652
new_size = toplevel->priv->drag_offset_y - y;
653
new_size = CLAMP (new_size, 0, monitor_height / 4);
654
new_y -= (new_size - toplevel->priv->size);
655
if (!toplevel->priv->y_centered && (new_y + new_size / 2) > monitor_height / 2)
656
new_y_bottom = monitor_height - (new_y + new_size);
660
case PANEL_GRAB_OP_RESIZE_DOWN:
661
new_size = y - toplevel->priv->drag_offset_y;
662
new_size = CLAMP (new_size, 0, monitor_height / 4);
663
if (!toplevel->priv->y_centered && (new_y + new_size / 2) > monitor_height / 2)
664
new_y_bottom = monitor_height - (new_y + new_size);
668
case PANEL_GRAB_OP_RESIZE_LEFT:
669
new_size = toplevel->priv->drag_offset_x - x;
670
new_size = CLAMP (new_size, 0, monitor_width / 4);
671
new_x -= (new_size - toplevel->priv->size);
672
if (!toplevel->priv->x_centered && (new_x + new_size / 2) > monitor_width / 2)
673
new_x_right = monitor_width - (new_x + new_size);
677
case PANEL_GRAB_OP_RESIZE_RIGHT:
678
new_size = x - toplevel->priv->drag_offset_x;
679
new_size = CLAMP (new_size, 0, monitor_width / 4);
680
if (!toplevel->priv->x_centered && (new_x + new_size / 2) > monitor_width / 2)
681
new_x_right = monitor_width - (new_x + new_size);
686
g_assert_not_reached ();
693
panel_toplevel_set_x (toplevel, new_x, new_x_right, new_x_centered);
694
panel_toplevel_set_y (toplevel, new_y, new_y_bottom, new_y_centered);
695
panel_toplevel_set_size (toplevel, new_size);
698
/* this is called for expanded panels that are dragged around */
700
panel_toplevel_calc_new_orientation (PanelToplevel *toplevel,
704
PanelOrientation new_orientation;
706
int hborder, vborder;
708
int monitor_width, monitor_height;
711
screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
713
monitor = panel_multiscreen_get_monitor_at_point (screen, pointer_x, pointer_y);
715
if (toplevel->priv->geometry.height < toplevel->priv->geometry.width)
716
vborder = hborder = (3 * toplevel->priv->geometry.height) >> 1;
718
vborder = hborder = (3 * toplevel->priv->geometry.width) >> 1;
720
new_x = pointer_x - panel_multiscreen_x (screen, monitor);
721
new_y = pointer_y - panel_multiscreen_y (screen, monitor);
722
monitor_width = panel_multiscreen_width (screen, monitor);
723
monitor_height = panel_multiscreen_height (screen, monitor);
725
new_orientation = toplevel->priv->orientation;
727
switch (toplevel->priv->orientation) {
728
case PANEL_ORIENTATION_TOP:
729
if (new_y > (monitor_height - hborder))
730
new_orientation = PANEL_ORIENTATION_BOTTOM;
732
else if (new_y > hborder) {
733
if (new_x > (monitor_width - vborder))
734
new_orientation = PANEL_ORIENTATION_RIGHT;
735
else if (new_x < vborder)
736
new_orientation = PANEL_ORIENTATION_LEFT;
739
case PANEL_ORIENTATION_BOTTOM:
741
new_orientation = PANEL_ORIENTATION_TOP;
743
else if (new_y < (monitor_height - hborder)) {
744
if (new_x > (monitor_width - vborder))
745
new_orientation = PANEL_ORIENTATION_RIGHT;
746
else if (new_x < vborder)
747
new_orientation = PANEL_ORIENTATION_LEFT;
750
case PANEL_ORIENTATION_LEFT:
751
if (new_x > (monitor_width - vborder))
752
new_orientation = PANEL_ORIENTATION_RIGHT;
754
else if (new_x > vborder) {
755
if (new_y > (monitor_height - hborder))
756
new_orientation = PANEL_ORIENTATION_BOTTOM;
757
else if (new_y < hborder)
758
new_orientation = PANEL_ORIENTATION_TOP;
761
case PANEL_ORIENTATION_RIGHT:
763
new_orientation = PANEL_ORIENTATION_LEFT;
765
else if (new_x < (monitor_width - vborder)) {
766
if (new_y > (monitor_height - hborder))
767
new_orientation = PANEL_ORIENTATION_BOTTOM;
768
else if (new_y < hborder)
769
new_orientation = PANEL_ORIENTATION_TOP;
773
g_assert_not_reached ();
777
panel_toplevel_set_monitor (toplevel, monitor);
778
panel_toplevel_set_orientation (toplevel, new_orientation);
782
panel_toplevel_move_to (PanelToplevel *toplevel,
787
PanelOrientation new_orientation;
788
gboolean x_centered, y_centered;
789
int screen_width, screen_height;
790
int monitor_width, monitor_height;
793
int x, y, x_right, y_bottom;
796
screen = panel_toplevel_get_screen_geometry (
797
toplevel, &screen_width, &screen_height);
799
width = toplevel->priv->geometry.width;
800
height = toplevel->priv->geometry.height;
802
snap_tolerance = toplevel->priv->snap_tolerance;
804
new_x = CLAMP (new_x, 0, screen_width - width);
805
new_y = CLAMP (new_y, 0, screen_height - height);
807
new_orientation = toplevel->priv->orientation;
809
if (new_x <= snap_tolerance &&
810
toplevel->priv->orientation & PANEL_VERTICAL_MASK)
811
new_orientation = PANEL_ORIENTATION_LEFT;
813
else if ((new_x + width) >= (screen_width - snap_tolerance) &&
814
toplevel->priv->orientation & PANEL_VERTICAL_MASK)
815
new_orientation = PANEL_ORIENTATION_RIGHT;
817
if (new_y <= snap_tolerance &&
818
toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
819
new_orientation = PANEL_ORIENTATION_TOP;
821
else if ((new_y + height) >= (screen_height - snap_tolerance) &&
822
toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
823
new_orientation = PANEL_ORIENTATION_BOTTOM;
825
new_monitor = panel_multiscreen_get_monitor_at_point (screen, new_x, new_y);
827
panel_toplevel_get_monitor_geometry (
828
toplevel, NULL, NULL, &monitor_width, &monitor_height);
830
x_centered = toplevel->priv->x_centered;
831
y_centered = toplevel->priv->y_centered;
833
x = new_x - panel_multiscreen_x (screen, new_monitor);
834
y = new_y - panel_multiscreen_y (screen, new_monitor);
836
if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
838
if (new_y <= snap_tolerance ||
839
new_y + height >= screen_height - snap_tolerance)
840
x_centered = abs (x - ((monitor_width - width) / 2))
846
if (new_x <= snap_tolerance ||
847
new_x + width >= screen_width - snap_tolerance)
848
y_centered = abs (y - ((monitor_height - height) / 2))
855
x = (monitor_width - width) / 2;
857
y = (monitor_height - height) / 2;
859
if (!x_centered && (x + width / 2) > monitor_width / 2)
860
x_right = monitor_width - (x + width);
864
if (!y_centered && (y + height / 2) > monitor_height / 2)
865
y_bottom = monitor_height - (y + height);
869
panel_toplevel_set_monitor (toplevel, new_monitor);
870
panel_toplevel_set_orientation (toplevel, new_orientation);
871
panel_toplevel_set_x (toplevel, x, x_right, x_centered);
872
panel_toplevel_set_y (toplevel, y, y_bottom, y_centered);
876
panel_toplevel_move_to_pointer (PanelToplevel *toplevel,
882
new_x = pointer_x - toplevel->priv->drag_offset_x;
883
new_y = pointer_y - toplevel->priv->drag_offset_y;
885
panel_toplevel_move_to (toplevel, new_x, new_y);
889
panel_toplevel_rotate_to_pointer (PanelToplevel *toplevel,
897
x = toplevel->priv->geometry.x;
898
y = toplevel->priv->geometry.y;
899
snap_tolerance = toplevel->priv->snap_tolerance;
901
x_diff = pointer_x - (x + toplevel->priv->geometry.width / 2);
902
y_diff = pointer_y - (y + toplevel->priv->geometry.height / 2);
904
if (((-y_diff > x_diff + snap_tolerance) && x_diff > 0 && y_diff < 0) ||
905
(( y_diff < x_diff + snap_tolerance) && x_diff < 0 && y_diff < 0))
906
panel_toplevel_set_orientation (toplevel, PANEL_ORIENTATION_RIGHT);
908
else if (((-x_diff < y_diff - snap_tolerance) && x_diff > 0 && y_diff < 0) ||
909
(( x_diff > y_diff - snap_tolerance) && x_diff > 0 && y_diff > 0))
910
panel_toplevel_set_orientation (toplevel, PANEL_ORIENTATION_BOTTOM);
912
else if ((( y_diff > x_diff + snap_tolerance) && x_diff > 0 && y_diff > 0) ||
913
((-y_diff < x_diff + snap_tolerance) && x_diff < 0 && y_diff > 0))
914
panel_toplevel_set_orientation (toplevel, PANEL_ORIENTATION_LEFT);
916
else if (((-x_diff > y_diff - snap_tolerance) && x_diff < 0 && y_diff > 0) ||
917
(( x_diff < y_diff - snap_tolerance) && x_diff < 0 && y_diff < 0))
918
panel_toplevel_set_orientation (toplevel, PANEL_ORIENTATION_TOP);
922
panel_toplevel_warp_pointer_increment (PanelToplevel *toplevel,
927
GdkWindow *root_window;
928
GdkModifierType modifier_mask;
931
screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
932
root_window = gdk_screen_get_root_window (screen);
934
gdk_window_get_device_position(root_window, gtk_get_current_event_device (), &new_x, &new_y, &modifier_mask);
942
case GDK_KEY_KP_Left:
946
case GDK_KEY_KP_Down:
950
case GDK_KEY_KP_Right:
954
g_assert_not_reached ();
958
panel_warp_pointer (root_window, new_x, new_y);
964
panel_toplevel_move_keyboard_floating (PanelToplevel *toplevel,
967
#define SMALL_INCREMENT 1
968
#define NORMAL_INCREMENT 10
970
int increment = NORMAL_INCREMENT;
972
if ((event->state & gtk_accelerator_get_default_mod_mask ()) == GDK_SHIFT_MASK)
973
increment = SMALL_INCREMENT;
975
return panel_toplevel_warp_pointer_increment (
976
toplevel, event->keyval, increment);
978
#undef SMALL_INCREMENT
979
#undef NORMAL_INCREMENT
983
panel_toplevel_move_keyboard_expanded (PanelToplevel *toplevel,
986
PanelOrientation new_orientation;
988
switch (event->keyval) {
991
new_orientation = PANEL_ORIENTATION_TOP;
994
case GDK_KEY_KP_Left:
995
new_orientation = PANEL_ORIENTATION_LEFT;
998
case GDK_KEY_KP_Down:
999
new_orientation = PANEL_ORIENTATION_BOTTOM;
1002
case GDK_KEY_KP_Right:
1003
new_orientation = PANEL_ORIENTATION_RIGHT;
1006
g_assert_not_reached ();
1010
panel_toplevel_set_orientation (toplevel, new_orientation);
1016
panel_toplevel_initial_resize_keypress (PanelToplevel *toplevel,
1019
PanelGrabOpType grab_op;
1021
switch (event->keyval) {
1024
if (!(toplevel->priv->orientation & PANEL_HORIZONTAL_MASK))
1026
grab_op = PANEL_GRAB_OP_RESIZE_UP;
1029
case GDK_KEY_KP_Left:
1030
if (!(toplevel->priv->orientation & PANEL_VERTICAL_MASK))
1032
grab_op = PANEL_GRAB_OP_RESIZE_LEFT;
1035
case GDK_KEY_KP_Down:
1036
if (!(toplevel->priv->orientation & PANEL_HORIZONTAL_MASK))
1038
grab_op = PANEL_GRAB_OP_RESIZE_DOWN;
1041
case GDK_KEY_KP_Right:
1042
if (!(toplevel->priv->orientation & PANEL_VERTICAL_MASK))
1044
grab_op = PANEL_GRAB_OP_RESIZE_RIGHT;
1047
g_assert_not_reached ();
1051
panel_toplevel_end_grab_op (toplevel, event->time);
1052
panel_toplevel_begin_grab_op (toplevel, grab_op, TRUE, event->time);
1058
panel_toplevel_handle_grab_op_key_event (PanelToplevel *toplevel,
1061
gboolean retval = FALSE;
1063
switch (event->keyval) {
1067
case GDK_KEY_KP_Left:
1069
case GDK_KEY_KP_Down:
1071
case GDK_KEY_KP_Right:
1072
switch (toplevel->priv->grab_op) {
1073
case PANEL_GRAB_OP_MOVE:
1074
if (toplevel->priv->expand)
1075
retval = panel_toplevel_move_keyboard_expanded (
1078
retval = panel_toplevel_move_keyboard_floating (
1081
case PANEL_GRAB_OP_RESIZE:
1082
retval = panel_toplevel_initial_resize_keypress (toplevel, event);
1084
case PANEL_GRAB_OP_RESIZE_UP:
1085
case PANEL_GRAB_OP_RESIZE_DOWN:
1086
case PANEL_GRAB_OP_RESIZE_LEFT:
1087
case PANEL_GRAB_OP_RESIZE_RIGHT:
1088
retval = panel_toplevel_warp_pointer_increment (
1089
toplevel, event->keyval, 1);
1092
g_assert_not_reached ();
1096
case GDK_KEY_Escape:
1097
panel_toplevel_cancel_grab_op (toplevel, event->time);
1098
case GDK_KEY_Return: /* drop through*/
1099
case GDK_KEY_KP_Enter:
1101
case GDK_KEY_KP_Space:
1102
panel_toplevel_end_grab_op (toplevel, event->time);
1104
default: /* drop through*/
1112
panel_toplevel_handle_grab_op_motion_event (PanelToplevel *toplevel,
1113
GdkEventMotion *event)
1115
switch (toplevel->priv->grab_op) {
1116
case PANEL_GRAB_OP_MOVE:
1117
if (toplevel->priv->expand)
1118
panel_toplevel_calc_new_orientation (
1119
toplevel, event->x_root, event->y_root);
1121
else if ((event->state & gtk_accelerator_get_default_mod_mask ()) == GDK_CONTROL_MASK)
1122
panel_toplevel_rotate_to_pointer (
1123
toplevel, event->x_root, event->y_root);
1126
panel_toplevel_move_to_pointer (
1127
toplevel, event->x_root, event->y_root);
1129
case PANEL_GRAB_OP_RESIZE_UP:
1130
case PANEL_GRAB_OP_RESIZE_DOWN:
1131
case PANEL_GRAB_OP_RESIZE_LEFT:
1132
case PANEL_GRAB_OP_RESIZE_RIGHT:
1133
panel_toplevel_resize_to_pointer (toplevel, event->x_root, event->y_root);
1143
panel_toplevel_calc_floating (PanelToplevel *toplevel)
1145
int screen_width, screen_height;
1146
int monitor_x, monitor_y;
1147
int monitor_width, monitor_height;
1151
if (toplevel->priv->expand) {
1152
toplevel->priv->floating = FALSE;
1156
panel_toplevel_get_screen_geometry (toplevel,
1157
&screen_width, &screen_height);
1158
panel_toplevel_get_monitor_geometry (toplevel, &monitor_x, &monitor_y,
1159
&monitor_width, &monitor_height);
1161
if (toplevel->priv->x_right == -1)
1162
x = monitor_x + toplevel->priv->x;
1164
x = monitor_x + (monitor_width - (toplevel->priv->x_right + toplevel->priv->geometry.width));
1165
if (toplevel->priv->y_bottom == -1)
1166
y = monitor_y + toplevel->priv->y;
1168
y = monitor_y + (monitor_height - (toplevel->priv->y_bottom + toplevel->priv->geometry.height));
1170
snap_tolerance = toplevel->priv->snap_tolerance;
1172
//FIXME? everywhere else, snap_tolerance is relative to the monitor,
1174
if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
1175
toplevel->priv->floating =
1176
(y > snap_tolerance) && (y < (screen_height - toplevel->priv->geometry.height - snap_tolerance));
1178
toplevel->priv->floating =
1179
(x > snap_tolerance) && (x < (screen_width - toplevel->priv->geometry.width - snap_tolerance));
1183
panel_toplevel_push_autohide_disabler (PanelToplevel *toplevel)
1185
g_return_if_fail (toplevel != NULL);
1187
if (!toplevel->priv->n_autohide_disablers++)
1188
panel_toplevel_queue_auto_hide (toplevel);
1192
panel_toplevel_pop_autohide_disabler (PanelToplevel *toplevel)
1194
g_return_if_fail (toplevel != NULL);
1195
g_return_if_fail (toplevel->priv->n_autohide_disablers > 0);
1197
if (!--toplevel->priv->n_autohide_disablers)
1198
panel_toplevel_queue_auto_hide (toplevel);
1202
panel_toplevel_get_autohide_disabled (PanelToplevel *toplevel)
1204
return toplevel->priv->n_autohide_disablers > 0 ? TRUE : FALSE;
1208
panel_toplevel_hide_button_event (PanelToplevel *toplevel,
1209
GdkEventButton *event,
1212
if (event->button == 1)
1215
return gtk_widget_event (GTK_WIDGET (toplevel), (GdkEvent *) event);
1219
panel_toplevel_hide_button_clicked (PanelToplevel *toplevel,
1222
GtkArrowType arrow_type;
1225
if (toplevel->priv->animating ||
1226
toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN)
1229
ltr = gtk_widget_get_direction (GTK_WIDGET (toplevel)) == GTK_TEXT_DIR_LTR;
1230
arrow_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "arrow-type"));
1232
if (toplevel->priv->state == PANEL_STATE_NORMAL) {
1233
GtkDirectionType direction = -1;
1235
switch (arrow_type) {
1237
direction = GTK_DIR_UP;
1239
case GTK_ARROW_DOWN:
1240
direction = GTK_DIR_DOWN;
1242
case GTK_ARROW_LEFT:
1243
direction = ltr ? GTK_DIR_LEFT : GTK_DIR_RIGHT;
1245
case GTK_ARROW_RIGHT:
1246
direction = ltr ? GTK_DIR_RIGHT : GTK_DIR_LEFT;
1249
g_assert_not_reached ();
1253
panel_toplevel_hide (toplevel, FALSE, direction);
1255
panel_toplevel_unhide (toplevel);
1259
panel_toplevel_add_hide_button (PanelToplevel *toplevel,
1260
GtkArrowType arrow_type,
1271
button = gtk_button_new ();
1272
obj = gtk_widget_get_accessible (button);
1273
atk_object_set_name (obj, _("Hide Panel"));
1274
gtk_widget_set_can_default (button, FALSE);
1276
gtk_widget_style_get (GTK_WIDGET (toplevel),
1277
"arrow-size", &arrow_size,
1280
switch (arrow_type) {
1282
gtk_widget_set_size_request (button, -1, arrow_size);
1284
case GTK_ARROW_DOWN:
1285
gtk_widget_set_size_request (button, -1, arrow_size);
1287
case GTK_ARROW_LEFT:
1288
gtk_widget_set_size_request (button, arrow_size, -1);
1290
case GTK_ARROW_RIGHT:
1291
gtk_widget_set_size_request (button, arrow_size, -1);
1294
g_assert_not_reached ();
1298
arrow = gtk_arrow_new (arrow_type, GTK_SHADOW_NONE);
1299
gtk_misc_set_padding (GTK_MISC (arrow), 0, 0);
1300
gtk_container_add (GTK_CONTAINER (button), arrow);
1301
gtk_widget_show (arrow);
1303
g_object_set_data (G_OBJECT (button),
1305
GINT_TO_POINTER (arrow_type));
1307
g_signal_connect_swapped (button, "clicked",
1308
G_CALLBACK (panel_toplevel_hide_button_clicked), toplevel);
1309
g_signal_connect_swapped (button, "button_press_event",
1310
G_CALLBACK (panel_toplevel_hide_button_event), toplevel);
1311
g_signal_connect_swapped (button, "button_release_event",
1312
G_CALLBACK (panel_toplevel_hide_button_event), toplevel);
1314
gtk_table_attach (GTK_TABLE (toplevel->priv->table),
1329
panel_toplevel_update_buttons_showing (PanelToplevel *toplevel)
1331
if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
1332
gtk_widget_hide (toplevel->priv->hide_button_top);
1333
gtk_widget_hide (toplevel->priv->hide_button_bottom);
1334
gtk_widget_show (toplevel->priv->hide_button_left);
1335
gtk_widget_show (toplevel->priv->hide_button_right);
1337
gtk_widget_show (toplevel->priv->hide_button_top);
1338
gtk_widget_show (toplevel->priv->hide_button_bottom);
1339
gtk_widget_hide (toplevel->priv->hide_button_left);
1340
gtk_widget_hide (toplevel->priv->hide_button_right);
1345
panel_toplevel_update_hide_buttons (PanelToplevel *toplevel)
1347
if (toplevel->priv->buttons_enabled)
1348
panel_toplevel_update_buttons_showing (toplevel);
1351
G_OBJECT (toplevel->priv->hide_button_top),
1352
"visible", toplevel->priv->state == PANEL_STATE_HIDDEN_DOWN,
1355
G_OBJECT (toplevel->priv->hide_button_bottom),
1356
"visible", toplevel->priv->state == PANEL_STATE_HIDDEN_UP,
1359
G_OBJECT (toplevel->priv->hide_button_left),
1360
"visible", toplevel->priv->state == PANEL_STATE_HIDDEN_RIGHT,
1363
G_OBJECT (toplevel->priv->hide_button_right),
1364
"visible", toplevel->priv->state == PANEL_STATE_HIDDEN_LEFT,
1368
if (toplevel->priv->arrows_enabled) {
1371
gtk_widget_show (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_top)));
1372
gtk_widget_show (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_bottom)));
1373
gtk_widget_show (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_left)));
1374
gtk_widget_show (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_right)));
1376
gtk_widget_style_get (GTK_WIDGET (toplevel),
1377
"arrow-size", &arrow_size,
1380
gtk_widget_set_size_request (toplevel->priv->hide_button_top,
1382
gtk_widget_set_size_request (toplevel->priv->hide_button_bottom,
1384
gtk_widget_set_size_request (toplevel->priv->hide_button_left,
1386
gtk_widget_set_size_request (toplevel->priv->hide_button_right,
1389
gtk_widget_hide (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_top)));
1390
gtk_widget_hide (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_bottom)));
1391
gtk_widget_hide (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_left)));
1392
gtk_widget_hide (gtk_bin_get_child (GTK_BIN (toplevel->priv->hide_button_right)));
1394
gtk_widget_set_size_request (toplevel->priv->hide_button_top, -1, -1);
1395
gtk_widget_set_size_request (toplevel->priv->hide_button_bottom, -1, -1);
1396
gtk_widget_set_size_request (toplevel->priv->hide_button_left, -1, -1);
1397
gtk_widget_set_size_request (toplevel->priv->hide_button_right, -1, -1);
1402
panel_toplevel_contains_pointer (PanelToplevel *toplevel)
1404
GdkDisplay *display;
1407
GdkDeviceManager *device_manager;
1411
display = gdk_display_get_default ();
1412
device_manager = gdk_display_get_device_manager (display);
1413
pointer = gdk_device_manager_get_client_pointer (device_manager);
1414
widget = GTK_WIDGET (toplevel);
1416
if (!gtk_widget_get_realized (widget))
1421
gdk_device_get_position (pointer, &screen, &x, &y);
1423
if (screen != gtk_window_get_screen (GTK_WINDOW (toplevel)))
1426
if (x == -1 || y == -1)
1429
if (x < toplevel->priv->geometry.x || x >= (toplevel->priv->geometry.x + toplevel->priv->geometry.width) ||
1430
y < toplevel->priv->geometry.y || y >= (toplevel->priv->geometry.y + toplevel->priv->geometry.height))
1437
panel_toplevel_get_effective_auto_hide_size (PanelToplevel *toplevel)
1441
if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
1442
size = CLAMP (toplevel->priv->auto_hide_size,
1443
1, toplevel->priv->original_height / 2);
1445
size = CLAMP (toplevel->priv->auto_hide_size,
1446
1, toplevel->priv->original_width / 2);
1449
return (size <= 0) ? DEFAULT_AUTO_HIDE_SIZE : size;
1453
panel_toplevel_update_struts (PanelToplevel *toplevel, gboolean end_of_animation)
1455
PanelOrientation orientation;
1457
gboolean geometry_changed = FALSE;
1458
int strut, strut_start, strut_end;
1459
int x, y, width, height;
1460
int monitor_x, monitor_y;
1461
int monitor_width, monitor_height;
1463
if (!toplevel->priv->updated_geometry_initial)
1466
/* In the case of the initial animation, we really want the struts to
1467
* represent what is at the end of the animation, to avoid desktop
1468
* icons jumping around. */
1469
if (!toplevel->priv->initial_animation_done) {
1470
end_of_animation = TRUE;
1472
/* We've not started the animation yet, so we have to compute
1473
* where we want to end. Note that we don't want to compute
1474
* this everytime, since the struts conflict resolution will be
1475
* overridden if we do so */
1476
if (!toplevel->priv->animating)
1477
panel_toplevel_calculate_animation_end_geometry (toplevel);
1480
screen = panel_toplevel_get_monitor_geometry (toplevel,
1486
if (end_of_animation) {
1487
x = toplevel->priv->animation_end_x;
1488
y = toplevel->priv->animation_end_y;
1489
x += panel_multiscreen_x (screen, toplevel->priv->monitor);
1490
y += panel_multiscreen_y (screen, toplevel->priv->monitor);
1491
if (toplevel->priv->animation_end_width != -1)
1492
width = toplevel->priv->animation_end_width;
1494
width = toplevel->priv->geometry.width;
1495
if (toplevel->priv->animation_end_height != -1)
1496
height = toplevel->priv->animation_end_height;
1498
height = toplevel->priv->geometry.height;
1500
x = toplevel->priv->geometry.x;
1501
y = toplevel->priv->geometry.y;
1502
width = toplevel->priv->geometry.width;
1503
height = toplevel->priv->geometry.height;
1506
orientation = toplevel->priv->orientation;
1508
strut = strut_start = strut_end = 0;
1510
if (orientation & PANEL_HORIZONTAL_MASK) {
1511
if (y <= monitor_y) {
1512
orientation = PANEL_ORIENTATION_TOP;
1513
strut = y + height - monitor_y;
1514
} else if (y >= monitor_y + monitor_height - height) {
1515
orientation = PANEL_ORIENTATION_BOTTOM;
1516
strut = monitor_y + monitor_height - y;
1520
strut_start = MAX (x, monitor_x);
1521
strut_end = MIN (x + width, monitor_x + monitor_width) - 1;
1524
if (x <= monitor_x) {
1525
orientation = PANEL_ORIENTATION_LEFT;
1526
strut = x + width - monitor_x;
1527
} else if (x >= monitor_x + monitor_width - width) {
1528
orientation = PANEL_ORIENTATION_RIGHT;
1529
strut = monitor_x + monitor_width - x;
1533
strut_start = MAX (y, monitor_y);
1534
strut_end = MIN (y + height, monitor_y + monitor_height) - 1;
1538
if (orientation != toplevel->priv->orientation) {
1539
toplevel->priv->orientation = orientation;
1540
g_object_notify (G_OBJECT (toplevel), "orientation");
1543
if (toplevel->priv->auto_hide && strut > 0)
1544
strut = panel_toplevel_get_effective_auto_hide_size (toplevel);
1547
geometry_changed = panel_struts_register_strut (toplevel,
1549
toplevel->priv->monitor,
1555
panel_struts_unregister_strut (toplevel);
1557
if (toplevel->priv->state == PANEL_STATE_NORMAL ||
1558
toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN ||
1559
toplevel->priv->animating)
1560
panel_struts_set_window_hint (toplevel);
1562
panel_struts_unset_window_hint (toplevel);
1564
return geometry_changed;
1568
panel_toplevel_update_edges (PanelToplevel *toplevel)
1571
PanelFrameEdge edges;
1572
PanelFrameEdge inner_edges;
1573
PanelFrameEdge outer_edges;
1574
PanelBackground *background;
1575
int monitor_width, monitor_height;
1577
gboolean inner_frame = FALSE;
1579
widget = GTK_WIDGET (toplevel);
1581
panel_toplevel_get_monitor_geometry (
1582
toplevel, NULL, NULL, &monitor_width, &monitor_height);
1584
width = toplevel->priv->geometry.width;
1585
height = toplevel->priv->geometry.height;
1587
edges = PANEL_EDGE_NONE;
1589
background = &toplevel->priv->panel_widget->background;
1591
/* We don't want any bevels with a color/image background */
1592
if (panel_background_effective_type (background) == PANEL_BACK_NONE) {
1593
if (toplevel->priv->geometry.y > 0)
1594
edges |= PANEL_EDGE_TOP;
1596
if (toplevel->priv->geometry.x > 0)
1597
edges |= PANEL_EDGE_LEFT;
1599
if (toplevel->priv->geometry.y < (monitor_height - height))
1600
edges |= PANEL_EDGE_BOTTOM;
1602
if (toplevel->priv->geometry.x < (monitor_width - width))
1603
edges |= PANEL_EDGE_RIGHT;
1605
/* There is a conflict in the position algorithm when a
1606
* non-expanded centered panel is nearly the size of the
1607
* screen. This is similar to the one we have in
1608
* panel_toplevel_update_position(). A simple solution is
1609
* to keep the bevels in this case. */
1610
if (!toplevel->priv->expand &&
1611
toplevel->priv->orientation & PANEL_HORIZONTAL_MASK &&
1612
toplevel->priv->x_centered)
1613
edges |= PANEL_EDGE_LEFT | PANEL_EDGE_RIGHT;
1615
if (!toplevel->priv->expand &&
1616
toplevel->priv->orientation & PANEL_VERTICAL_MASK &&
1617
toplevel->priv->y_centered)
1618
edges |= PANEL_EDGE_TOP | PANEL_EDGE_BOTTOM;
1620
if (gtk_widget_get_visible (toplevel->priv->hide_button_left) ||
1621
gtk_widget_get_visible (toplevel->priv->hide_button_right)) {
1623
edges |= PANEL_EDGE_LEFT | PANEL_EDGE_RIGHT;
1626
if (gtk_widget_get_visible (toplevel->priv->hide_button_top) ||
1627
gtk_widget_get_visible (toplevel->priv->hide_button_bottom)) {
1629
edges |= PANEL_EDGE_TOP | PANEL_EDGE_BOTTOM;
1634
inner_edges = PANEL_EDGE_NONE;
1635
outer_edges = edges;
1637
inner_edges = edges;
1638
outer_edges = PANEL_EDGE_NONE;
1641
panel_frame_set_edges (toplevel->priv->inner_frame, inner_edges);
1643
if (toplevel->priv->edges != outer_edges) {
1644
toplevel->priv->edges = outer_edges;
1645
gtk_widget_queue_resize (widget);
1650
panel_toplevel_construct_description (PanelToplevel *toplevel)
1652
int orientation, type;
1654
static const char *description[4][4] = {
1656
/* translators: these string will be shown in MetaCity's switch window
1657
* popup when you pass the focus to a panel */
1658
N_("Top Expanded Edge Panel"),
1659
N_("Top Centered Panel"),
1660
N_("Top Floating Panel"),
1661
N_("Top Edge Panel"),
1665
N_("Bottom Expanded Edge Panel"),
1666
N_("Bottom Centered Panel"),
1667
N_("Bottom Floating Panel"),
1668
N_("Bottom Edge Panel"),
1672
N_("Left Expanded Edge Panel"),
1673
N_("Left Centered Panel"),
1674
N_("Left Floating Panel"),
1675
N_("Left Edge Panel"),
1679
N_("Right Expanded Edge Panel"),
1680
N_("Right Centered Panel"),
1681
N_("Right Floating Panel"),
1682
N_("Right Edge Panel"),
1686
switch (toplevel->priv->orientation) {
1687
case PANEL_ORIENTATION_TOP:
1690
case PANEL_ORIENTATION_BOTTOM:
1693
case PANEL_ORIENTATION_LEFT:
1696
case PANEL_ORIENTATION_RIGHT:
1701
g_assert_not_reached ();
1705
if (toplevel->priv->expand)
1707
else if (toplevel->priv->x_centered ||
1708
toplevel->priv->y_centered)
1710
else if (toplevel->priv->floating)
1715
return description[orientation][type];
1719
panel_toplevel_update_description (PanelToplevel *toplevel)
1721
const char *description;
1723
description = panel_toplevel_construct_description (toplevel);
1725
if (toplevel->priv->description &&
1726
!strcmp (toplevel->priv->description, description))
1729
if (toplevel->priv->description)
1730
g_free (toplevel->priv->description);
1731
toplevel->priv->description = g_strdup (_(description));
1733
if (!toplevel->priv->name)
1734
gtk_window_set_title (GTK_WINDOW (toplevel),
1735
toplevel->priv->description);
1737
panel_a11y_set_atk_name_desc (
1738
GTK_WIDGET (toplevel->priv->panel_widget),
1739
toplevel->priv->name ? toplevel->priv->name :
1740
_(toplevel->priv->description),
1741
_(toplevel->priv->description));
1745
panel_toplevel_update_normal_position (PanelToplevel *toplevel,
1751
int monitor_width, monitor_height;
1755
g_assert (x != NULL && y != NULL);
1757
panel_toplevel_get_monitor_geometry (
1758
toplevel, NULL, NULL, &monitor_width, &monitor_height);
1760
width = toplevel->priv->original_width;
1761
height = toplevel->priv->original_height;
1762
snap_tolerance = toplevel->priv->snap_tolerance;
1764
*x = CLAMP (*x, 0, monitor_width - width);
1765
*y = CLAMP (*y, 0, monitor_height - height);
1767
if (toplevel->priv->x <= snap_tolerance &&
1768
toplevel->priv->x_right == -1 &&
1769
!toplevel->priv->x_centered)
1771
else if (toplevel->priv->x_right != -1 &&
1772
toplevel->priv->x_right <= snap_tolerance &&
1773
!toplevel->priv->x_centered)
1774
*x = monitor_width - width;
1776
if (toplevel->priv->y <= snap_tolerance &&
1777
toplevel->priv->y_bottom == -1 &&
1778
!toplevel->priv->y_centered)
1780
else if (toplevel->priv->y_bottom != -1 &&
1781
toplevel->priv->y_bottom <= snap_tolerance &&
1782
!toplevel->priv->y_centered)
1783
*y = monitor_height - height;
1787
panel_toplevel_update_auto_hide_position (PanelToplevel *toplevel,
1792
gboolean for_end_position)
1795
int monitor_width, monitor_height;
1799
g_assert (x != NULL && y != NULL);
1801
if (toplevel->priv->floating) {
1802
panel_toplevel_update_normal_position (toplevel, x, y, w, h);
1806
panel_toplevel_get_monitor_geometry (
1807
toplevel, NULL, NULL, &monitor_width, &monitor_height);
1809
width = toplevel->priv->original_width;
1810
height = toplevel->priv->original_height;
1811
snap_tolerance = toplevel->priv->snap_tolerance;
1813
/* For the initial animation, we animate from outside the screen, and
1814
* so we don't want the toplevel to be visible at all. But when the
1815
* request is for the end position, then we give the real result (it's
1816
* useful for struts) */
1817
if (for_end_position || toplevel->priv->initial_animation_done) {
1818
auto_hide_size = panel_toplevel_get_effective_auto_hide_size (toplevel);
1823
switch (toplevel->priv->orientation) {
1824
case PANEL_ORIENTATION_TOP:
1825
*y = - (height - auto_hide_size);
1827
case PANEL_ORIENTATION_BOTTOM:
1828
*y = monitor_height - auto_hide_size;
1830
case PANEL_ORIENTATION_LEFT:
1831
*x = - (width - auto_hide_size);
1833
case PANEL_ORIENTATION_RIGHT:
1834
*x = monitor_width - auto_hide_size;
1837
g_assert_not_reached ();
1841
if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
1842
if (toplevel->priv->x <= snap_tolerance &&
1843
toplevel->priv->x_right == -1 &&
1844
!toplevel->priv->x_centered)
1846
else if (toplevel->priv->x_right != -1 &&
1847
toplevel->priv->x_right <= snap_tolerance &&
1848
!toplevel->priv->x_centered)
1849
*x = monitor_width - width;
1850
} else /* if (toplevel->priv->orientation & PANEL_VERTICAL_MASK) */ {
1851
if (toplevel->priv->y <= snap_tolerance &&
1852
toplevel->priv->y_bottom == -1 &&
1853
!toplevel->priv->y_centered)
1855
else if (toplevel->priv->y_bottom != -1 &&
1856
toplevel->priv->y_bottom <= snap_tolerance &&
1857
!toplevel->priv->y_centered)
1858
*y = monitor_height - height;
1862
/* FIXME: this is wrong for Xinerama. In the Xinerama case
1863
* I think if hiding it requires it to go onto the
1864
* next monitor then it should just move it on to
1865
* the next monitor and set its state back to normal
1868
panel_toplevel_update_hidden_position (PanelToplevel *toplevel,
1876
int monitor_height, monitor_width;
1877
GtkAllocation hide_allocation;
1879
g_assert (x != NULL && y != NULL);
1881
g_assert (toplevel->priv->state == PANEL_STATE_HIDDEN_UP ||
1882
toplevel->priv->state == PANEL_STATE_HIDDEN_DOWN ||
1883
toplevel->priv->state == PANEL_STATE_HIDDEN_LEFT ||
1884
toplevel->priv->state == PANEL_STATE_HIDDEN_RIGHT);
1886
panel_toplevel_get_monitor_geometry (
1887
toplevel, NULL, NULL, &monitor_width, &monitor_height);
1889
width = toplevel->priv->original_width;
1890
height = toplevel->priv->original_height;
1892
//FIXME should find a better default
1893
min_hide_size = DEFAULT_AUTO_HIDE_SIZE;
1895
switch (toplevel->priv->state) {
1896
case PANEL_STATE_HIDDEN_UP:
1897
gtk_widget_get_allocation (toplevel->priv->hide_button_bottom,
1899
*y = - (height - MAX (hide_allocation.height, min_hide_size));
1901
case PANEL_STATE_HIDDEN_DOWN:
1902
gtk_widget_get_allocation (toplevel->priv->hide_button_top,
1904
*y = monitor_height - MAX (hide_allocation.height, min_hide_size);
1906
case PANEL_STATE_HIDDEN_LEFT:
1907
gtk_widget_get_allocation (toplevel->priv->hide_button_right,
1909
*x = - (width - MAX (hide_allocation.width, min_hide_size));
1911
case PANEL_STATE_HIDDEN_RIGHT:
1912
gtk_widget_get_allocation (toplevel->priv->hide_button_left,
1914
*x = monitor_width - MAX (hide_allocation.width, min_hide_size);
1917
g_assert_not_reached ();
1923
* This is "almost" like the double sine movement
1924
* from the original panel except that it uses
1925
* a cubic (twice again). I suppose it looks less
1926
* mathematical now :) -- _v_
1931
GTimeVal *start_time,
1935
double x, s, n, d, percentage;
1937
s = start_time->tv_sec + ((double)start_time->tv_usec / G_USEC_PER_SEC);
1938
n = cur_time->tv_sec + ((double)cur_time->tv_usec / G_USEC_PER_SEC);
1939
d = end_time->tv_sec + ((double)end_time->tv_usec / G_USEC_PER_SEC);
1944
if (abs (dest - src) <= 1 || n >= d)
1947
/* The cubic is: p(x) = (-2) x^2 (x-1.5) */
1948
/* running p(p(x)) to make it more "pronounced",
1949
* effectively making it a ninth-degree polynomial */
1952
x = -2 * (x*x) * (x-1.5);
1954
percentage = -2 * (x*x) * (x-1.5);
1956
percentage = CLAMP (percentage, 0.0, 1.0);
1958
return ((dest - src) * percentage);
1962
panel_toplevel_update_animating_position (PanelToplevel *toplevel)
1966
int deltax, deltay, deltaw = 0, deltah = 0;
1967
int monitor_offset_x, monitor_offset_y;
1969
g_get_current_time (&time_val);
1971
screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
1973
monitor_offset_x = panel_multiscreen_x (screen, toplevel->priv->monitor);
1974
monitor_offset_y = panel_multiscreen_y (screen, toplevel->priv->monitor);
1976
if (toplevel->priv->animation_end_width != -1)
1977
deltaw = get_delta (toplevel->priv->geometry.width,
1978
toplevel->priv->animation_end_width,
1979
&toplevel->priv->animation_start_time,
1980
&toplevel->priv->animation_end_time,
1983
if (toplevel->priv->animation_end_height != -1)
1984
deltah = get_delta (toplevel->priv->geometry.height,
1985
toplevel->priv->animation_end_height,
1986
&toplevel->priv->animation_start_time,
1987
&toplevel->priv->animation_end_time,
1990
deltax = get_delta (toplevel->priv->geometry.x - monitor_offset_x,
1991
toplevel->priv->animation_end_x,
1992
&toplevel->priv->animation_start_time,
1993
&toplevel->priv->animation_end_time,
1996
deltay = get_delta (toplevel->priv->geometry.y - monitor_offset_y,
1997
toplevel->priv->animation_end_y,
1998
&toplevel->priv->animation_start_time,
1999
&toplevel->priv->animation_end_time,
2002
if (deltaw != 0 && abs (deltaw) > abs (deltax))
2004
if (deltah != 0 && abs (deltah) > abs (deltay))
2007
toplevel->priv->geometry.x += deltax;
2008
toplevel->priv->geometry.y += deltay;
2010
toplevel->priv->geometry.width += deltaw;
2011
toplevel->priv->geometry.height += deltah;
2013
if (toplevel->priv->geometry.x - monitor_offset_x == toplevel->priv->animation_end_x &&
2014
toplevel->priv->geometry.y - monitor_offset_y == toplevel->priv->animation_end_y) {
2015
toplevel->priv->animating = FALSE;
2016
/* Note: it's important to set initial_animation_done to TRUE
2017
* as soon as possible (hence, here) since we don't want to
2018
* have a wrong value in a size request event */
2019
toplevel->priv->initial_animation_done = TRUE;
2021
gtk_widget_queue_resize (GTK_WIDGET (toplevel));
2023
if (toplevel->priv->state == PANEL_STATE_NORMAL)
2024
g_signal_emit (toplevel, toplevel_signals [UNHIDE_SIGNAL], 0);
2029
panel_toplevel_update_expanded_position (PanelToplevel *toplevel)
2032
int monitor_width, monitor_height;
2033
int screen_width, screen_height;
2034
int monitor_x, monitor_y;
2036
int x_right, y_bottom;
2039
if (!toplevel->priv->expand)
2042
screen = panel_toplevel_get_screen_geometry (toplevel,
2046
panel_toplevel_get_monitor_geometry (toplevel, &monitor_x, &monitor_y,
2047
&monitor_width, &monitor_height);
2054
switch (toplevel->priv->orientation) {
2055
case PANEL_ORIENTATION_TOP:
2059
case PANEL_ORIENTATION_LEFT:
2063
case PANEL_ORIENTATION_BOTTOM:
2065
y = monitor_y + monitor_height - toplevel->priv->geometry.height;
2068
case PANEL_ORIENTATION_RIGHT:
2069
x = monitor_x + monitor_width - toplevel->priv->geometry.width;
2074
g_assert_not_reached ();
2078
monitor = panel_multiscreen_get_monitor_at_point (screen, x, y);
2080
panel_toplevel_set_monitor_internal (toplevel, monitor, TRUE);
2082
x -= panel_multiscreen_x (screen, monitor);
2083
y -= panel_multiscreen_y (screen, monitor);
2085
g_object_freeze_notify (G_OBJECT (toplevel));
2087
if (toplevel->priv->x != x) {
2088
toplevel->priv->x = x;
2089
g_object_notify (G_OBJECT (toplevel), "x");
2092
if (toplevel->priv->y != y) {
2093
toplevel->priv->y = y;
2094
g_object_notify (G_OBJECT (toplevel), "y");
2097
if (toplevel->priv->x_right != x_right) {
2098
toplevel->priv->x_right = x_right;
2099
g_object_notify (G_OBJECT (toplevel), "x_right");
2102
if (toplevel->priv->y_bottom != y_bottom) {
2103
toplevel->priv->y_bottom = y_bottom;
2104
g_object_notify (G_OBJECT (toplevel), "y_bottom");
2107
g_object_thaw_notify (G_OBJECT (toplevel));
2111
panel_toplevel_update_position (PanelToplevel *toplevel)
2113
PanelBackground *background;
2117
int screen_width, screen_height;
2118
int monitor_width, monitor_height;
2120
screen = panel_toplevel_get_screen_geometry (
2121
toplevel, &screen_width, &screen_height);
2123
panel_toplevel_get_monitor_geometry (
2124
toplevel, NULL, NULL, &monitor_width, &monitor_height);
2126
if (toplevel->priv->animating) {
2127
panel_toplevel_update_animating_position (toplevel);
2131
if (toplevel->priv->position_centered) {
2132
toplevel->priv->position_centered = FALSE;
2134
g_object_freeze_notify (G_OBJECT (toplevel));
2136
if (!toplevel->priv->x_centered) {
2139
toplevel->priv->x -= toplevel->priv->geometry.width / 2;
2140
g_object_notify (G_OBJECT (toplevel), "x");
2142
if ((toplevel->priv->x + toplevel->priv->geometry.width / 2) > monitor_width / 2)
2143
x_right = monitor_width - (toplevel->priv->x + toplevel->priv->geometry.width);
2146
if (toplevel->priv->x_right != x_right) {
2147
toplevel->priv->x_right = x_right;
2148
g_object_notify (G_OBJECT (toplevel),
2153
if (!toplevel->priv->y_centered) {
2156
toplevel->priv->y -= toplevel->priv->geometry.height / 2;
2157
g_object_notify (G_OBJECT (toplevel), "y");
2159
if ((toplevel->priv->y + toplevel->priv->geometry.height / 2) > monitor_height / 2)
2160
y_bottom = monitor_height - (toplevel->priv->y + toplevel->priv->geometry.height);
2163
if (toplevel->priv->y_bottom != y_bottom) {
2164
toplevel->priv->y_bottom = y_bottom;
2165
g_object_notify (G_OBJECT (toplevel),
2170
g_object_thaw_notify (G_OBJECT (toplevel));
2173
panel_toplevel_update_expanded_position (toplevel);
2174
panel_toplevel_calc_floating (toplevel); //FIXME should probably be done after panel_toplevel_update_normal_position() too
2176
if (toplevel->priv->x_right == -1)
2177
x = toplevel->priv->x;
2179
x = monitor_width - (toplevel->priv->x_right + toplevel->priv->geometry.width);
2180
if (toplevel->priv->y_bottom == -1)
2181
y = toplevel->priv->y;
2183
y = monitor_height - (toplevel->priv->y_bottom + toplevel->priv->geometry.height);
2185
if (!toplevel->priv->expand) {
2186
if (toplevel->priv->x_centered)
2187
x = (monitor_width - toplevel->priv->geometry.width) / 2;
2188
if (toplevel->priv->y_centered)
2189
y = (monitor_height - toplevel->priv->geometry.height) / 2;
2194
if (toplevel->priv->state == PANEL_STATE_NORMAL)
2195
panel_toplevel_update_normal_position (toplevel, &x, &y, &w, &h);
2197
else if (toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN)
2198
panel_toplevel_update_auto_hide_position (toplevel, &x, &y, &w, &h, FALSE);
2201
panel_toplevel_update_hidden_position (toplevel, &x, &y, &w, &h);
2204
toplevel->priv->geometry.width = w;
2206
toplevel->priv->geometry.height = h;
2208
/* This is some kind of snap: there's a possibility of an infinite loop
2209
* because of the bevels of the frame that are set in
2210
* panel_toplevel_update_edges(). The bevels change the width/height of
2211
* the toplevel. The typical loop is:
2212
* x = 1 => outer bevel => x = 0 => no outer bevel = > x = 1 => ...
2213
* FIXME: maybe the real bug is that we enter into this loop (see bug
2214
* #160748 to learn how to reproduce.) */
2215
background = &toplevel->priv->panel_widget->background;
2216
/* There's no bevels with a color/image background */
2217
if (panel_background_effective_type (background) == PANEL_BACK_NONE) {
2218
GtkStyleContext *context;
2219
GtkStateFlags state;
2220
GdkRectangle *geometry;
2224
state = gtk_widget_get_state_flags (GTK_WIDGET (toplevel->priv->inner_frame));
2225
context = gtk_widget_get_style_context (GTK_WIDGET (toplevel->priv->inner_frame));
2226
gtk_style_context_get_padding (context, state, &padding);
2227
geometry = &toplevel->priv->geometry;
2229
if (x <= padding.left && x > 0 &&
2230
!toplevel->priv->x_centered)
2233
if (y <= padding.top && y > 0 &&
2234
!toplevel->priv->y_centered)
2237
max_size = monitor_width - geometry->width - padding.right;
2238
if (x + padding.left >= max_size && x < max_size &&
2239
!toplevel->priv->x_centered)
2242
max_size = monitor_height - geometry->height - padding.bottom;
2243
if (y + padding.top >= max_size && y < max_size &&
2244
!toplevel->priv->y_centered)
2248
x += panel_multiscreen_x (screen, toplevel->priv->monitor);
2249
y += panel_multiscreen_y (screen, toplevel->priv->monitor);
2251
toplevel->priv->geometry.x = x;
2252
toplevel->priv->geometry.y = y;
2256
calculate_minimum_height (GtkWidget *widget,
2257
PanelOrientation orientation)
2259
GtkStateFlags state;
2260
GtkStyleContext *style_context;
2261
const PangoFontDescription *font_desc;
2262
PangoContext *pango_context;
2263
PangoFontMetrics *metrics;
2265
int focus_width = 0;
2271
state = gtk_widget_get_state_flags (widget);
2272
style_context = gtk_widget_get_style_context (widget);
2273
gtk_style_context_get (style_context, state, "font", &font_desc, NULL);
2275
pango_context = gtk_widget_get_pango_context (widget);
2276
metrics = pango_context_get_metrics (pango_context,
2278
pango_context_get_language (pango_context));
2279
ascent = pango_font_metrics_get_ascent (metrics);
2280
descent = pango_font_metrics_get_descent (metrics);
2282
pango_font_metrics_unref (metrics);
2284
gtk_style_context_get_padding (style_context, state, &padding);
2285
gtk_widget_style_get (widget,
2286
"focus-line-width", &focus_width,
2287
"focus-padding", &focus_pad,
2290
thickness = orientation & PANEL_HORIZONTAL_MASK ?
2291
padding.top + padding.bottom :
2292
padding.left + padding.right;
2294
return PANGO_PIXELS (ascent + descent) + 2 * (focus_width + focus_pad) + thickness;
2298
panel_toplevel_update_size_from_hints (PanelToplevel *toplevel,
2299
int requisition_size,
2301
int non_panel_widget_size)
2304
AppletSizeHints *applets_hints;
2305
AppletSizeHintsAlloc *using_hint;
2311
total_size = non_panel_widget_size + requisition_size;
2313
nb_size_hints = toplevel->priv->panel_widget->nb_applets_size_hints;
2314
if (nb_size_hints <= 0)
2317
applets_hints = toplevel->priv->panel_widget->applets_hints;
2318
using_hint = toplevel->priv->panel_widget->applets_using_hint;
2320
for (i = 0; i < nb_size_hints; i++) {
2321
using_hint[i].index = applets_hints[i].len - 2;
2322
using_hint[i].size = applets_hints[i].hints[applets_hints[i].len - 1];
2323
total_size += using_hint[i].size;
2326
if (total_size > monitor_size)
2327
return monitor_size;
2330
while (full_hints != nb_size_hints && total_size < monitor_size) {
2334
bonus = (monitor_size - total_size)
2335
/ (nb_size_hints - full_hints);
2336
extra_bonus = (monitor_size - total_size)
2337
% (nb_size_hints - full_hints);
2340
for (i = 0; i < nb_size_hints; i++) {
2344
current_bonus = bonus;
2346
/* first find the (max, min) range in hints that we
2347
* will use; since we try to allocate as much size as
2348
* possible, this means we want the (max, min) range
2349
* where min is the highest possible (ie, the range
2350
* with the smaller index possible), while still
2351
* keeping min smaller than the potential new size */
2352
while (using_hint[i].index > 0 &&
2353
applets_hints[i].hints[using_hint[i].index - 1] < using_hint[i].size + current_bonus) {
2354
new_size = applets_hints[i].hints[using_hint[i].index - 1];
2355
current_bonus = using_hint[i].size
2356
+ current_bonus - new_size;
2357
total_size = total_size - using_hint[i].size
2360
using_hint[i].index -= 2;
2361
using_hint[i].size = new_size;
2364
/* now, give the bonus, while still keeping a size that
2365
* is lower than max from the (max, min) range we've
2367
new_size = MIN (applets_hints[i].hints[using_hint[i].index],
2368
using_hint[i].size + current_bonus);
2369
if (new_size > using_hint[i].size) {
2370
total_size += (new_size - using_hint[i].size);
2371
using_hint[i].size = new_size;
2375
/* if there's some extra bonus to take, try to allocate
2377
if (extra_bonus > 0) {
2378
new_size = MIN (applets_hints[i].hints[using_hint[i].index],
2379
using_hint[i].size + extra_bonus);
2380
if (new_size > using_hint[i].size) {
2381
total_size += (new_size
2382
- using_hint[i].size);
2383
extra_bonus -= (new_size
2384
- using_hint[i].size);
2385
using_hint[i].size = new_size;
2389
if (using_hint[i].size == applets_hints[i].hints[using_hint[i].index])
2398
panel_toplevel_update_size (PanelToplevel *toplevel,
2399
GtkRequisition *requisition)
2402
GtkStyleContext *context;
2403
GtkStateFlags state;
2405
int monitor_width, monitor_height;
2408
int non_panel_widget_size;
2410
if (toplevel->priv->animating)
2413
widget = GTK_WIDGET (toplevel);
2414
state = gtk_widget_get_state_flags (widget);
2415
context = gtk_widget_get_style_context (widget);
2416
gtk_style_context_get_padding (context, state, &padding);
2418
panel_toplevel_get_monitor_geometry (
2419
toplevel, NULL, NULL, &monitor_width, &monitor_height);
2421
width = requisition->width;
2422
height = requisition->height;
2424
if (!toplevel->priv->expand &&
2425
!toplevel->priv->buttons_enabled)
2426
non_panel_widget_size = 2 * HANDLE_SIZE;
2428
non_panel_widget_size = 0;
2430
minimum_height = calculate_minimum_height (GTK_WIDGET (toplevel),
2431
toplevel->priv->orientation);
2433
if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
2435
height = MAX (MIN (MAX (height, toplevel->priv->size),
2436
panel_toplevel_get_maximum_size (toplevel)),
2439
if (toplevel->priv->expand)
2440
width = monitor_width;
2442
width = panel_toplevel_update_size_from_hints (
2446
non_panel_widget_size);
2448
width = MAX (MINIMUM_WIDTH, width);
2450
width = MAX (MIN (MAX (width, toplevel->priv->size),
2451
panel_toplevel_get_maximum_size (toplevel)),
2454
if (toplevel->priv->expand)
2455
height = monitor_height;
2457
height = panel_toplevel_update_size_from_hints (
2459
requisition->height,
2461
non_panel_widget_size);
2463
height = MAX (MINIMUM_WIDTH, height);
2466
if (toplevel->priv->edges & PANEL_EDGE_TOP)
2467
height += padding.top;
2468
if (toplevel->priv->edges & PANEL_EDGE_BOTTOM)
2469
height += padding.bottom;
2470
if (toplevel->priv->edges & PANEL_EDGE_LEFT)
2471
width += padding.left;
2472
if (toplevel->priv->edges & PANEL_EDGE_RIGHT)
2473
width += padding.right;
2475
toplevel->priv->geometry.width = CLAMP (width, 0, monitor_width);
2476
toplevel->priv->geometry.height = CLAMP (height, 0, monitor_height);
2477
toplevel->priv->original_width = toplevel->priv->geometry.width;
2478
toplevel->priv->original_height = toplevel->priv->geometry.height;
2482
panel_toplevel_update_geometry (PanelToplevel *toplevel,
2483
GtkRequisition *requisition)
2485
toplevel->priv->updated_geometry_initial = TRUE;
2486
panel_toplevel_update_size (toplevel, requisition);
2487
panel_toplevel_update_position (toplevel);
2489
panel_toplevel_update_struts (toplevel, FALSE);
2491
if (toplevel->priv->state == PANEL_STATE_NORMAL ||
2492
toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN) {
2493
panel_struts_update_toplevel_geometry (toplevel,
2494
&toplevel->priv->geometry.x,
2495
&toplevel->priv->geometry.y,
2496
&toplevel->priv->geometry.width,
2497
&toplevel->priv->geometry.height);
2499
panel_struts_update_toplevel_geometry (toplevel,
2500
&toplevel->priv->geometry.x,
2501
&toplevel->priv->geometry.y,
2505
panel_toplevel_update_edges (toplevel);
2506
panel_toplevel_update_description (toplevel);
2510
panel_toplevel_popup_panel_menu (PanelToplevel *toplevel)
2512
gboolean retval = FALSE;
2514
g_signal_emit_by_name (toplevel, "popup_menu", &retval);
2520
panel_toplevel_toggle_expand (PanelToplevel *toplevel)
2522
panel_toplevel_set_expand (toplevel, !toplevel->priv->expand);
2528
panel_toplevel_expand (PanelToplevel *toplevel)
2530
panel_toplevel_set_expand (toplevel, TRUE);
2536
panel_toplevel_unexpand (PanelToplevel *toplevel)
2538
panel_toplevel_set_expand (toplevel, FALSE);
2544
panel_toplevel_toggle_hidden (PanelToplevel *toplevel)
2546
if (toplevel->priv->state == PANEL_STATE_NORMAL)
2547
panel_toplevel_hide (toplevel, toplevel->priv->auto_hide, -1);
2549
panel_toplevel_unhide (toplevel);
2555
panel_toplevel_begin_move (PanelToplevel *toplevel)
2557
if (toplevel->priv->grab_op != PANEL_GRAB_OP_NONE)
2560
panel_toplevel_begin_grab_op (
2561
toplevel, PANEL_GRAB_OP_MOVE, TRUE, GDK_CURRENT_TIME);
2567
panel_toplevel_begin_resize (PanelToplevel *toplevel)
2569
if (toplevel->priv->grab_op != PANEL_GRAB_OP_NONE)
2572
panel_toplevel_begin_grab_op (
2573
toplevel, PANEL_GRAB_OP_RESIZE, TRUE, GDK_CURRENT_TIME);
2579
panel_toplevel_move_resize_window (PanelToplevel *toplevel,
2585
widget = GTK_WIDGET (toplevel);
2587
g_assert (gtk_widget_get_realized (widget));
2590
gdk_window_move_resize (gtk_widget_get_window (widget),
2591
toplevel->priv->geometry.x,
2592
toplevel->priv->geometry.y,
2593
toplevel->priv->geometry.width,
2594
toplevel->priv->geometry.height);
2596
gdk_window_move (gtk_widget_get_window (widget),
2597
toplevel->priv->geometry.x,
2598
toplevel->priv->geometry.y);
2600
gdk_window_resize (gtk_widget_get_window (widget),
2601
toplevel->priv->geometry.width,
2602
toplevel->priv->geometry.height);
2606
panel_toplevel_initially_hide (PanelToplevel *toplevel)
2608
toplevel->priv->initial_animation_done = FALSE;
2610
/* We start the panel off hidden until all the applets are
2611
* loaded, and then finally slide it down when it's ready to be
2613
toplevel->priv->state = PANEL_STATE_AUTO_HIDDEN;
2614
gtk_widget_queue_resize (GTK_WIDGET (toplevel));
2618
panel_toplevel_realize (GtkWidget *widget)
2620
PanelToplevel *toplevel = (PanelToplevel *) widget;
2623
gtk_window_set_decorated (GTK_WINDOW (widget), FALSE);
2624
gtk_window_stick (GTK_WINDOW (widget));
2626
if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->realize)
2627
GTK_WIDGET_CLASS (panel_toplevel_parent_class)->realize (widget);
2629
window = gtk_widget_get_window (widget);
2631
panel_struts_set_window_hint (toplevel);
2632
panel_xutils_set_window_type (window, PANEL_XUTILS_TYPE_DOCK);
2634
gdk_window_set_group (window, window);
2635
gdk_window_set_geometry_hints (window, NULL, GDK_HINT_POS);
2637
panel_toplevel_initially_hide (toplevel);
2639
panel_toplevel_move_resize_window (toplevel, TRUE, TRUE);
2643
panel_toplevel_disconnect_timeouts (PanelToplevel *toplevel)
2645
if (toplevel->priv->hide_timeout)
2646
g_source_remove (toplevel->priv->hide_timeout);
2647
toplevel->priv->hide_timeout = 0;
2649
if (toplevel->priv->unhide_timeout)
2650
g_source_remove (toplevel->priv->unhide_timeout);
2651
toplevel->priv->unhide_timeout = 0;
2653
if (toplevel->priv->animation_timeout)
2654
g_source_remove (toplevel->priv->animation_timeout);
2655
toplevel->priv->animation_timeout = 0;
2659
panel_toplevel_unrealize (GtkWidget *widget)
2661
panel_toplevel_disconnect_timeouts (PANEL_TOPLEVEL (widget));
2663
if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->unrealize)
2664
GTK_WIDGET_CLASS (panel_toplevel_parent_class)->unrealize (widget);
2668
panel_toplevel_dispose (GObject *widget)
2670
PanelToplevel *toplevel = (PanelToplevel *) widget;
2672
panel_toplevel_disconnect_timeouts (toplevel);
2674
G_OBJECT_CLASS (panel_toplevel_parent_class)->dispose (widget);
2678
panel_toplevel_check_resize (GtkContainer *container)
2680
GtkAllocation allocation;
2681
GtkRequisition requisition;
2684
widget = GTK_WIDGET (container);
2686
if (!gtk_widget_get_visible (widget))
2689
gtk_widget_get_preferred_size (widget, &requisition, NULL);
2690
gtk_widget_get_allocation (widget, &allocation);
2692
allocation.width = requisition.width;
2693
allocation.height = requisition.height;
2695
gtk_widget_size_allocate (widget, &allocation);
2699
panel_toplevel_size_request (GtkWidget *widget,
2700
GtkRequisition *requisition)
2702
PanelToplevel *toplevel;
2705
GdkRectangle old_geometry;
2706
int position_changed = FALSE;
2707
int size_changed = FALSE;
2708
int dummy; /* to pass a valid pointer */
2710
toplevel = PANEL_TOPLEVEL (widget);
2711
bin = GTK_BIN (widget);
2713
/* we get a size request when there are new monitors, so first try to
2714
* see if we need to move to a new monitor */
2715
panel_toplevel_update_monitor (toplevel);
2717
child = gtk_bin_get_child (bin);
2718
if (child && gtk_widget_get_visible (child)) {
2719
gtk_widget_get_preferred_width (child, &dummy, &requisition->width);
2720
gtk_widget_get_preferred_height (child, &dummy, &requisition->height);
2723
old_geometry = toplevel->priv->geometry;
2725
panel_toplevel_update_geometry (toplevel, requisition);
2727
requisition->width = toplevel->priv->geometry.width;
2728
requisition->height = toplevel->priv->geometry.height;
2730
if (!gtk_widget_get_realized (widget))
2733
if (old_geometry.width != toplevel->priv->geometry.width ||
2734
old_geometry.height != toplevel->priv->geometry.height)
2735
size_changed = TRUE;
2737
if (old_geometry.x != toplevel->priv->geometry.x ||
2738
old_geometry.y != toplevel->priv->geometry.y)
2739
position_changed = TRUE;
2741
panel_toplevel_move_resize_window (toplevel, position_changed, size_changed);
2745
panel_toplevel_get_preferred_width(GtkWidget *widget, gint *minimal_width, gint *natural_width)
2747
GtkRequisition requisition;
2749
panel_toplevel_size_request (widget, &requisition);
2751
*minimal_width = *natural_width = requisition.width;
2755
panel_toplevel_get_preferred_height(GtkWidget *widget, gint *minimal_height, gint *natural_height)
2757
GtkRequisition requisition;
2759
panel_toplevel_size_request (widget, &requisition);
2761
*minimal_height = *natural_height = requisition.height;
2765
panel_toplevel_size_allocate (GtkWidget *widget,
2766
GtkAllocation *allocation)
2768
PanelToplevel *toplevel = (PanelToplevel *) widget;
2769
GtkBin *bin = (GtkBin *) widget;
2770
GtkStyleContext *context;
2771
GtkStateFlags state;
2774
GtkAllocation challoc;
2775
GtkAllocation child_allocation;
2777
gtk_widget_set_allocation (widget, allocation);
2779
if (toplevel->priv->expand ||
2780
toplevel->priv->buttons_enabled)
2781
challoc = *allocation;
2783
if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
2784
challoc.x = HANDLE_SIZE;
2786
challoc.width = allocation->width - 2 * HANDLE_SIZE;
2787
challoc.height = allocation->height;
2790
challoc.y = HANDLE_SIZE;
2791
challoc.width = allocation->width;
2792
challoc.height = allocation->height - 2 * HANDLE_SIZE;
2796
state = gtk_widget_get_state_flags (widget);
2797
context = gtk_widget_get_style_context (widget);
2798
gtk_style_context_get_padding (context, state, &padding);
2800
if (toplevel->priv->edges & PANEL_EDGE_TOP) {
2801
challoc.y += padding.top;
2802
challoc.height -= padding.top;
2805
if (toplevel->priv->edges & PANEL_EDGE_LEFT) {
2806
challoc.x += padding.left;
2807
challoc.width -= padding.left;
2810
if (toplevel->priv->edges & PANEL_EDGE_BOTTOM)
2811
challoc.height -= padding.bottom;
2813
if (toplevel->priv->edges & PANEL_EDGE_RIGHT)
2814
challoc.width -= padding.right;
2816
challoc.width = MAX (1, challoc.width);
2817
challoc.height = MAX (1, challoc.height);
2819
child = gtk_bin_get_child (bin);
2820
gtk_widget_get_allocation (child, &child_allocation);
2822
if (gtk_widget_get_mapped (widget) &&
2823
(challoc.x != child_allocation.x ||
2824
challoc.y != child_allocation.y ||
2825
challoc.width != child_allocation.width ||
2826
challoc.height != child_allocation.height)) {
2827
GtkAllocation allocation;
2829
gtk_widget_get_allocation (widget, &allocation);
2830
gdk_window_invalidate_rect (gtk_widget_get_window (widget), &allocation, FALSE);
2833
if (child && gtk_widget_get_visible (child))
2834
gtk_widget_size_allocate (child, &challoc);
2838
panel_toplevel_draw (GtkWidget *widget,
2841
PanelToplevel *toplevel = (PanelToplevel *) widget;
2842
PanelFrameEdge edges;
2843
gboolean retval = FALSE;
2844
GtkStyleContext *context;
2845
GtkStateFlags state;
2847
int awidth, aheight;
2849
if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->draw)
2850
retval = GTK_WIDGET_CLASS (panel_toplevel_parent_class)->draw (widget, cr);
2852
edges = toplevel->priv->edges;
2853
/* FIXMEchpe: WTF!? */
2854
panel_frame_draw (widget, cr, edges);
2856
if (toplevel->priv->expand ||
2857
toplevel->priv->buttons_enabled)
2860
state = gtk_widget_get_state_flags (widget);
2861
awidth = gtk_widget_get_allocated_width (widget);
2862
aheight = gtk_widget_get_allocated_height (widget);
2864
context = gtk_widget_get_style_context (widget);
2865
gtk_style_context_get_padding (context, state, &padding);
2867
gtk_style_context_save (context);
2868
gtk_style_context_set_state (context, state);
2870
if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
2871
int x, y, width, height;
2875
width = HANDLE_SIZE;
2878
if (edges & PANEL_EDGE_TOP) {
2880
height -= padding.top;
2882
if (edges & PANEL_EDGE_BOTTOM)
2883
height -= padding.bottom;
2884
if (edges & PANEL_EDGE_LEFT)
2888
gtk_render_handle (context, cr, x, y, width, height);
2891
x = awidth - HANDLE_SIZE;
2892
if (edges & PANEL_EDGE_RIGHT)
2896
gtk_render_handle (context, cr, x, y, width, height);
2899
int x, y, width, height;
2904
height = HANDLE_SIZE;
2906
if (edges & PANEL_EDGE_LEFT) {
2908
width -= padding.left;
2910
if (edges & PANEL_EDGE_RIGHT)
2911
width -= padding.right;
2912
if (edges & PANEL_EDGE_TOP)
2916
gtk_render_handle (context, cr, x, y, width, height);
2919
y = aheight - HANDLE_SIZE;
2920
if (edges & PANEL_EDGE_BOTTOM)
2921
y -= padding.bottom;
2924
gtk_render_handle (context, cr, x, y, width, height);
2928
gtk_style_context_restore (context);
2934
panel_toplevel_button_press_event (GtkWidget *widget,
2935
GdkEventButton *event)
2937
PanelToplevel *toplevel;
2939
GtkWidget *event_widget;
2941
g_return_val_if_fail (PANEL_IS_TOPLEVEL (widget), FALSE);
2943
toplevel = PANEL_TOPLEVEL (widget);
2945
if (event->button != 1 && event->button != 2)
2948
if (toplevel->priv->animating)
2951
modifiers = event->state & gtk_accelerator_get_default_mod_mask ();
2953
/* Get the mouse-button modifier from metacity so that only intentional
2954
* moves are considered. We don't this for non-expanded panels since we
2955
* only have the handles that the user can grab. */
2956
if (toplevel->priv->expand &&
2957
modifiers != panel_bindings_get_mouse_button_modifier_keymask ())
2960
gdk_window_get_user_data (event->window, (gpointer)&event_widget);
2961
g_assert (GTK_IS_WIDGET (event_widget));
2962
gtk_widget_translate_coordinates (event_widget,
2966
&toplevel->priv->drag_offset_x,
2967
&toplevel->priv->drag_offset_y);
2969
panel_toplevel_begin_grab_op (toplevel, PANEL_GRAB_OP_MOVE, FALSE, event->time);
2975
panel_toplevel_button_release_event (GtkWidget *widget,
2976
GdkEventButton *event)
2978
PanelToplevel *toplevel;
2980
if (event->button != 1 && event->button != 2)
2983
toplevel = PANEL_TOPLEVEL (widget);
2985
if (toplevel->priv->grab_op == PANEL_GRAB_OP_NONE)
2988
if (toplevel->priv->grab_is_keyboard)
2991
panel_toplevel_end_grab_op (toplevel, event->time);
2997
panel_toplevel_key_press_event (GtkWidget *widget,
3000
PanelToplevel *toplevel = (PanelToplevel *) widget;
3002
if (toplevel->priv->grab_op != PANEL_GRAB_OP_NONE &&
3003
panel_toplevel_handle_grab_op_key_event (toplevel, event))
3006
if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->key_press_event)
3007
return GTK_WIDGET_CLASS (panel_toplevel_parent_class)->key_press_event (widget, event);
3013
panel_toplevel_motion_notify_event (GtkWidget *widget,
3014
GdkEventMotion *event)
3016
if (gdk_event_get_screen ((GdkEvent *)event) ==
3017
gtk_window_get_screen (GTK_WINDOW (widget)))
3018
return panel_toplevel_handle_grab_op_motion_event (
3019
PANEL_TOPLEVEL (widget), event);
3025
panel_toplevel_animation_timeout (PanelToplevel *toplevel)
3027
gtk_widget_queue_resize (GTK_WIDGET (toplevel));
3029
if (!toplevel->priv->animating) {
3030
toplevel->priv->animation_end_x = 0xdead;
3031
toplevel->priv->animation_end_y = 0xdead;
3032
toplevel->priv->animation_end_width = 0xdead;
3033
toplevel->priv->animation_end_height = 0xdead;
3034
toplevel->priv->animation_start_time.tv_sec = 0xdead;
3035
toplevel->priv->animation_start_time.tv_usec = 0xdead;
3036
toplevel->priv->animation_end_time.tv_sec = 0xdead;
3037
toplevel->priv->animation_end_time.tv_usec = 0xdead;
3038
toplevel->priv->animation_timeout = 0;
3039
toplevel->priv->initial_animation_done = TRUE;
3042
return toplevel->priv->animating;
3046
panel_toplevel_get_animation_time (PanelToplevel *toplevel)
3048
/* The number of seconds to complete the animation.
3050
#define ANIMATION_TIME_FAST 0.4
3051
#define ANIMATION_TIME_MEDIUM 1.2
3052
#define ANIMATION_TIME_SLOW 2.0
3056
switch (toplevel->priv->animation_speed) {
3057
case PANEL_ANIMATION_SLOW:
3058
t = ANIMATION_TIME_SLOW * G_USEC_PER_SEC;
3060
case PANEL_ANIMATION_MEDIUM:
3061
t = ANIMATION_TIME_MEDIUM * G_USEC_PER_SEC;
3063
case PANEL_ANIMATION_FAST:
3064
t = ANIMATION_TIME_FAST * G_USEC_PER_SEC;
3067
g_assert_not_reached ();
3073
#undef ANIMATION_TIME_FAST
3074
#undef ANIMATION_TIME_MEDIUM
3075
#undef ANIMATION_TIME_SLOW
3079
panel_toplevel_calculate_animation_end_geometry (PanelToplevel *toplevel)
3081
int monitor_width, monitor_height;
3083
toplevel->priv->animation_end_x = toplevel->priv->x;
3084
toplevel->priv->animation_end_y = toplevel->priv->y;
3085
toplevel->priv->animation_end_width = -1;
3086
toplevel->priv->animation_end_height = -1;
3088
panel_toplevel_get_monitor_geometry (
3089
toplevel, NULL, NULL, &monitor_width, &monitor_height);
3091
if (!toplevel->priv->expand) {
3093
if (toplevel->priv->x_centered)
3094
toplevel->priv->animation_end_x =
3095
(monitor_width - toplevel->priv->geometry.width) / 2;
3096
if (toplevel->priv->y_centered)
3097
toplevel->priv->animation_end_y =
3098
(monitor_height - toplevel->priv->geometry.height) / 2;
3101
/* we consider the toplevels which are in the initial animation stage
3102
* as in a normal state */
3103
if (toplevel->priv->state == PANEL_STATE_NORMAL ||
3104
(!toplevel->priv->initial_animation_done &&
3105
!toplevel->priv->auto_hide))
3106
panel_toplevel_update_normal_position (toplevel,
3107
&toplevel->priv->animation_end_x,
3108
&toplevel->priv->animation_end_y,
3109
&toplevel->priv->animation_end_width,
3110
&toplevel->priv->animation_end_height);
3112
else if (toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN)
3113
panel_toplevel_update_auto_hide_position (toplevel,
3114
&toplevel->priv->animation_end_x,
3115
&toplevel->priv->animation_end_y,
3116
&toplevel->priv->animation_end_width,
3117
&toplevel->priv->animation_end_height,
3120
panel_toplevel_update_hidden_position (toplevel,
3121
&toplevel->priv->animation_end_x,
3122
&toplevel->priv->animation_end_y,
3123
&toplevel->priv->animation_end_width,
3124
&toplevel->priv->animation_end_height);
3128
panel_toplevel_start_animation (PanelToplevel *toplevel)
3131
GtkRequisition requisition;
3132
int deltax, deltay, deltaw = 0, deltah = 0;
3133
int cur_x = -1, cur_y = -1;
3136
panel_toplevel_calculate_animation_end_geometry (toplevel);
3138
toplevel->priv->animating = TRUE;
3140
panel_toplevel_update_struts (toplevel, TRUE);
3141
panel_struts_update_toplevel_geometry (toplevel,
3142
&toplevel->priv->animation_end_x,
3143
&toplevel->priv->animation_end_y,
3144
&toplevel->priv->animation_end_width,
3145
&toplevel->priv->animation_end_height);
3146
panel_toplevel_update_struts (toplevel, FALSE);
3148
gdk_window_get_origin (gtk_widget_get_window (GTK_WIDGET (toplevel)), &cur_x, &cur_y);
3150
screen = gtk_widget_get_screen (GTK_WIDGET (toplevel));
3152
cur_x -= panel_multiscreen_x (screen, toplevel->priv->monitor);
3153
cur_y -= panel_multiscreen_y (screen, toplevel->priv->monitor);
3155
deltax = toplevel->priv->animation_end_x - cur_x;
3156
deltay = toplevel->priv->animation_end_y - cur_y;
3158
gtk_widget_get_requisition (GTK_WIDGET (toplevel), &requisition);
3160
if (toplevel->priv->animation_end_width != -1)
3161
deltaw = toplevel->priv->animation_end_width - requisition.width;
3163
if (toplevel->priv->animation_end_height != -1)
3164
deltah = toplevel->priv->animation_end_height - requisition.height;
3166
if (deltax == 0 && deltay == 0 && deltaw == 0 && deltah == 0) {
3167
toplevel->priv->animation_end_x = -1;
3168
toplevel->priv->animation_end_y = -1;
3169
toplevel->priv->animation_end_width = -1;
3170
toplevel->priv->animation_end_height = -1;
3171
toplevel->priv->animating = FALSE;
3175
g_get_current_time (&toplevel->priv->animation_start_time);
3177
t = panel_toplevel_get_animation_time (toplevel);
3178
g_get_current_time (&toplevel->priv->animation_end_time);
3179
g_time_val_add (&toplevel->priv->animation_end_time, t);
3181
if (!toplevel->priv->animation_timeout)
3182
toplevel->priv->animation_timeout =
3183
g_timeout_add (20, (GSourceFunc) panel_toplevel_animation_timeout, toplevel);
3187
panel_toplevel_hide (PanelToplevel *toplevel,
3189
GtkDirectionType direction)
3191
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
3193
if (toplevel->priv->state != PANEL_STATE_NORMAL)
3196
g_signal_emit (toplevel, toplevel_signals [HIDE_SIGNAL], 0);
3199
toplevel->priv->state = PANEL_STATE_AUTO_HIDDEN;
3201
if (direction == -1) {
3202
if (toplevel->priv->orientation & PANEL_VERTICAL_MASK)
3203
direction = GTK_DIR_UP;
3205
direction = GTK_DIR_LEFT;
3208
switch (direction) {
3210
g_return_if_fail (toplevel->priv->orientation & PANEL_VERTICAL_MASK);
3211
toplevel->priv->state = PANEL_STATE_HIDDEN_UP;
3214
g_return_if_fail (toplevel->priv->orientation & PANEL_VERTICAL_MASK);
3215
toplevel->priv->state = PANEL_STATE_HIDDEN_DOWN;
3218
g_return_if_fail (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK);
3219
toplevel->priv->state = PANEL_STATE_HIDDEN_LEFT;
3222
g_return_if_fail (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK);
3223
toplevel->priv->state = PANEL_STATE_HIDDEN_RIGHT;
3226
g_assert_not_reached ();
3230
panel_toplevel_update_hide_buttons (toplevel);
3233
if (toplevel->priv->animate && gtk_widget_get_realized (GTK_WIDGET (toplevel)))
3234
panel_toplevel_start_animation (toplevel);
3236
gtk_widget_queue_resize (GTK_WIDGET (toplevel));
3240
panel_toplevel_auto_hide_timeout_handler (PanelToplevel *toplevel)
3242
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
3244
if (panel_toplevel_get_autohide_disabled (toplevel)) {
3245
toplevel->priv->hide_timeout = 0;
3249
/* keep coming back until the animation has finished.
3250
* FIXME: we should really remove the timeout/idle
3251
* completely and re-instate it when the
3252
* animation has finished.
3254
if (toplevel->priv->animating)
3257
panel_toplevel_hide (toplevel, TRUE, -1);
3259
toplevel->priv->hide_timeout = 0;
3265
panel_toplevel_unhide (PanelToplevel *toplevel)
3267
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
3269
if (toplevel->priv->state == PANEL_STATE_NORMAL)
3272
toplevel->priv->state = PANEL_STATE_NORMAL;
3274
panel_toplevel_update_hide_buttons (toplevel);
3276
if (toplevel->priv->animate && gtk_widget_get_realized (GTK_WIDGET (toplevel)))
3277
panel_toplevel_start_animation (toplevel);
3279
gtk_widget_queue_resize (GTK_WIDGET (toplevel));
3281
if (!toplevel->priv->animate)
3282
g_signal_emit (toplevel, toplevel_signals [UNHIDE_SIGNAL], 0);
3286
panel_toplevel_auto_unhide_timeout_handler (PanelToplevel *toplevel)
3288
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
3290
/* keep coming back until the animation has finished.
3291
* FIXME: we should really remove the timeout/idle
3292
* completely and re-instate it when the
3293
* animation has finished.
3295
if (toplevel->priv->animating)
3298
if (!toplevel->priv->animate)
3299
toplevel->priv->initial_animation_done = TRUE;
3301
/* initial animation for auto-hidden panels: we need to unhide and hide
3302
* again to get at the right size */
3303
if (!toplevel->priv->initial_animation_done &&
3304
toplevel->priv->auto_hide) {
3305
toplevel->priv->unhide_timeout = 0;
3306
panel_toplevel_unhide (toplevel);
3307
panel_toplevel_hide (toplevel, TRUE, -1);
3311
if (!panel_toplevel_contains_pointer (toplevel) &&
3312
toplevel->priv->auto_hide) {
3313
toplevel->priv->unhide_timeout = 0;
3317
panel_toplevel_unhide (toplevel);
3319
toplevel->priv->unhide_timeout = 0;
3325
panel_toplevel_queue_auto_hide (PanelToplevel *toplevel)
3327
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
3329
if (!toplevel->priv->auto_hide ||
3330
panel_toplevel_contains_pointer (toplevel) ||
3331
panel_toplevel_get_autohide_disabled (toplevel))
3334
if (toplevel->priv->unhide_timeout)
3335
g_source_remove (toplevel->priv->unhide_timeout);
3336
toplevel->priv->unhide_timeout = 0;
3338
if (toplevel->priv->hide_timeout ||
3339
toplevel->priv->state != PANEL_STATE_NORMAL)
3342
if (toplevel->priv->hide_delay > 0)
3343
toplevel->priv->hide_timeout =
3344
g_timeout_add (toplevel->priv->hide_delay,
3345
(GSourceFunc) panel_toplevel_auto_hide_timeout_handler,
3348
toplevel->priv->hide_timeout =
3349
g_idle_add ((GSourceFunc) panel_toplevel_auto_hide_timeout_handler,
3354
panel_toplevel_queue_auto_unhide (PanelToplevel *toplevel)
3356
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
3358
if (toplevel->priv->unhide_timeout)
3361
if (toplevel->priv->hide_timeout)
3362
g_source_remove (toplevel->priv->hide_timeout);
3363
toplevel->priv->hide_timeout = 0;
3365
if (toplevel->priv->state != PANEL_STATE_AUTO_HIDDEN)
3368
if (toplevel->priv->unhide_delay > 0)
3369
toplevel->priv->unhide_timeout =
3370
g_timeout_add (toplevel->priv->unhide_delay,
3371
(GSourceFunc) panel_toplevel_auto_unhide_timeout_handler,
3374
toplevel->priv->unhide_timeout =
3375
g_idle_add ((GSourceFunc) panel_toplevel_auto_unhide_timeout_handler,
3380
panel_toplevel_queue_initial_unhide (PanelToplevel *toplevel)
3382
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
3384
if (toplevel->priv->initial_animation_done)
3387
if (toplevel->priv->unhide_timeout)
3390
toplevel->priv->unhide_timeout =
3391
g_idle_add ((GSourceFunc) panel_toplevel_auto_unhide_timeout_handler,
3396
panel_toplevel_enter_notify_event (GtkWidget *widget,
3397
GdkEventCrossing *event)
3399
PanelToplevel *toplevel;
3401
g_return_val_if_fail (PANEL_IS_TOPLEVEL (widget), FALSE);
3403
toplevel = PANEL_TOPLEVEL (widget);
3405
if (toplevel->priv->auto_hide && event->detail != GDK_NOTIFY_INFERIOR)
3406
panel_toplevel_queue_auto_unhide (toplevel);
3408
if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->enter_notify_event)
3409
return GTK_WIDGET_CLASS (panel_toplevel_parent_class)->enter_notify_event (widget, event);
3415
panel_toplevel_leave_notify_event (GtkWidget *widget,
3416
GdkEventCrossing *event)
3418
PanelToplevel *toplevel;
3420
g_return_val_if_fail (PANEL_IS_TOPLEVEL (widget), FALSE);
3422
toplevel = PANEL_TOPLEVEL (widget);
3424
if (toplevel->priv->auto_hide && event->detail != GDK_NOTIFY_INFERIOR)
3425
panel_toplevel_queue_auto_hide (toplevel);
3427
if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->leave_notify_event)
3428
return GTK_WIDGET_CLASS (panel_toplevel_parent_class)->leave_notify_event (widget, event);
3434
panel_toplevel_focus_in_event (GtkWidget *widget,
3435
GdkEventFocus *event)
3437
PanelToplevel *toplevel = PANEL_TOPLEVEL (widget);
3439
if (toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN)
3440
panel_toplevel_unhide (toplevel);
3442
if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->focus_in_event)
3443
return GTK_WIDGET_CLASS (panel_toplevel_parent_class)->focus_in_event (widget, event);
3449
panel_toplevel_focus_out_event (GtkWidget *widget,
3450
GdkEventFocus *event)
3452
PanelToplevel *toplevel = PANEL_TOPLEVEL (widget);
3454
/* It appears that sometimes we don't get a leave notify event,
3455
but just a focus in/out, so queue the autohide in that case.
3456
If the pointer is inside the panel then obviously we won't hide */
3457
if (toplevel->priv->auto_hide)
3458
panel_toplevel_queue_auto_hide (toplevel);
3460
if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->focus_out_event)
3461
return GTK_WIDGET_CLASS (panel_toplevel_parent_class)->focus_out_event (widget, event);
3467
panel_toplevel_style_updated (GtkWidget *widget)
3469
panel_toplevel_update_hide_buttons (PANEL_TOPLEVEL (widget));
3471
if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->style_updated)
3472
GTK_WIDGET_CLASS (panel_toplevel_parent_class)->style_updated (widget);
3476
panel_toplevel_drag_threshold_changed (PanelToplevel *toplevel)
3481
g_object_get (G_OBJECT (toplevel->priv->gtk_settings),
3482
"gtk-dnd-drag-threshold", &threshold,
3486
toplevel->priv->snap_tolerance = threshold * SNAP_TOLERANCE_FACTOR;
3490
panel_toplevel_enable_animations_changed (PanelToplevel *toplevel)
3492
gboolean enable_animations;
3494
enable_animations = TRUE;
3495
g_object_get (G_OBJECT (toplevel->priv->gtk_settings),
3496
"gtk-enable-animations", &enable_animations,
3499
panel_toplevel_set_animate (toplevel, enable_animations);
3503
panel_toplevel_disconnect_gtk_settings (PanelToplevel *toplevel)
3505
if (!toplevel->priv->gtk_settings)
3508
g_signal_handlers_disconnect_by_func (toplevel->priv->gtk_settings,
3509
G_CALLBACK (panel_toplevel_drag_threshold_changed),
3511
g_signal_handlers_disconnect_by_func (toplevel->priv->gtk_settings,
3512
G_CALLBACK (panel_toplevel_enable_animations_changed),
3517
panel_toplevel_update_gtk_settings (PanelToplevel *toplevel)
3519
panel_toplevel_disconnect_gtk_settings (toplevel);
3521
toplevel->priv->gtk_settings = gtk_widget_get_settings (GTK_WIDGET (toplevel->priv->panel_widget));
3523
g_signal_connect_swapped (G_OBJECT (toplevel->priv->gtk_settings),
3524
"notify::gtk-dnd-drag-threshold",
3525
G_CALLBACK (panel_toplevel_drag_threshold_changed),
3528
panel_toplevel_drag_threshold_changed (toplevel);
3530
g_signal_connect_swapped (G_OBJECT (toplevel->priv->gtk_settings),
3531
"notify::gtk-enable-animations",
3532
G_CALLBACK (panel_toplevel_enable_animations_changed),
3535
panel_toplevel_enable_animations_changed (toplevel);
3539
panel_toplevel_screen_changed (GtkWidget *widget,
3540
GdkScreen *previous_screen)
3542
panel_toplevel_update_gtk_settings (PANEL_TOPLEVEL (widget));
3544
if (GTK_WIDGET_CLASS (panel_toplevel_parent_class)->screen_changed)
3545
GTK_WIDGET_CLASS (panel_toplevel_parent_class)->screen_changed (widget, previous_screen);
3547
gtk_widget_queue_resize (widget);
3551
panel_toplevel_constructor (GType type,
3552
guint n_construct_properties,
3553
GObjectConstructParam *construct_properties)
3556
PanelToplevel *toplevel;
3558
obj = G_OBJECT_CLASS (panel_toplevel_parent_class)->constructor (type,
3559
n_construct_properties,
3560
construct_properties);
3562
toplevel = PANEL_TOPLEVEL (obj);
3564
/* We can't do that in init() as init() will set the properties to
3565
* their default, and this would write to gsettings */
3566
panel_toplevel_bind_gsettings (toplevel);
3572
panel_toplevel_set_property (GObject *object,
3574
const GValue *value,
3577
PanelToplevel *toplevel;
3579
g_return_if_fail (PANEL_IS_TOPLEVEL (object));
3581
toplevel = PANEL_TOPLEVEL (object);
3584
case PROP_TOPLEVEL_ID:
3585
panel_toplevel_set_toplevel_id (toplevel, g_value_get_string (value));
3587
case PROP_SETTINGS_PATH:
3588
panel_toplevel_set_settings_path (toplevel, g_value_get_string (value));
3591
panel_toplevel_set_name (toplevel, g_value_get_string (value));
3594
panel_toplevel_set_expand (toplevel, g_value_get_boolean (value));
3596
case PROP_ORIENTATION:
3597
panel_toplevel_set_orientation (toplevel, g_value_get_enum (value));
3600
panel_toplevel_set_size (toplevel, g_value_get_int (value));
3603
panel_toplevel_set_x (toplevel,
3604
g_value_get_int (value),
3605
toplevel->priv->x_right,
3606
toplevel->priv->x_centered);
3609
panel_toplevel_set_x (toplevel,
3611
g_value_get_int (value),
3612
toplevel->priv->x_centered);
3614
case PROP_X_CENTERED:
3615
panel_toplevel_set_x (toplevel,
3617
toplevel->priv->x_right,
3618
g_value_get_boolean (value));
3621
panel_toplevel_set_y (toplevel,
3622
g_value_get_int (value),
3623
toplevel->priv->y_bottom,
3624
toplevel->priv->y_centered);
3627
panel_toplevel_set_y (toplevel,
3629
g_value_get_int (value),
3630
toplevel->priv->y_centered);
3632
case PROP_Y_CENTERED:
3633
panel_toplevel_set_y (toplevel,
3635
toplevel->priv->y_bottom,
3636
g_value_get_boolean (value));
3639
panel_toplevel_set_monitor (toplevel, g_value_get_int (value));
3642
panel_toplevel_set_auto_hide (toplevel, g_value_get_boolean (value));
3644
case PROP_HIDE_DELAY:
3645
panel_toplevel_set_hide_delay (toplevel, g_value_get_int (value));
3647
case PROP_UNHIDE_DELAY:
3648
panel_toplevel_set_unhide_delay (toplevel, g_value_get_int (value));
3650
case PROP_AUTOHIDE_SIZE:
3651
panel_toplevel_set_auto_hide_size (toplevel, g_value_get_int (value));
3654
panel_toplevel_set_animate (toplevel, g_value_get_boolean (value));
3656
case PROP_ANIMATION_SPEED:
3657
panel_toplevel_set_animation_speed (toplevel, g_value_get_enum (value));
3659
case PROP_BUTTONS_ENABLED:
3660
panel_toplevel_set_enable_buttons (toplevel, g_value_get_boolean (value));
3662
case PROP_ARROWS_ENABLED:
3663
panel_toplevel_set_enable_arrows (toplevel, g_value_get_boolean (value));
3666
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3672
panel_toplevel_get_property (GObject *object,
3677
PanelToplevel *toplevel;
3679
g_return_if_fail (PANEL_IS_TOPLEVEL (object));
3681
toplevel = PANEL_TOPLEVEL (object);
3684
case PROP_TOPLEVEL_ID:
3685
g_value_set_string (value, toplevel->priv->toplevel_id);
3687
case PROP_SETTINGS_PATH:
3688
g_value_set_string (value, toplevel->priv->settings_path);
3691
g_value_set_string (value, panel_toplevel_get_name (toplevel));
3694
g_value_set_boolean (value, toplevel->priv->expand);
3696
case PROP_ORIENTATION:
3697
g_value_set_enum (value, toplevel->priv->orientation);
3700
g_value_set_int (value, toplevel->priv->size);
3703
g_value_set_int (value, toplevel->priv->x);
3706
g_value_set_int (value, toplevel->priv->x_right);
3708
case PROP_X_CENTERED:
3709
g_value_set_boolean (value, toplevel->priv->x_centered);
3712
g_value_set_int (value, toplevel->priv->y);
3715
g_value_set_int (value, toplevel->priv->y_bottom);
3717
case PROP_Y_CENTERED:
3718
g_value_set_boolean (value, toplevel->priv->y_centered);
3721
g_value_set_int (value, toplevel->priv->monitor);
3724
g_value_set_boolean (value, toplevel->priv->auto_hide);
3726
case PROP_HIDE_DELAY:
3727
g_value_set_int (value, toplevel->priv->hide_delay);
3729
case PROP_UNHIDE_DELAY:
3730
g_value_set_int (value, toplevel->priv->unhide_delay);
3732
case PROP_AUTOHIDE_SIZE:
3733
g_value_set_int (value, toplevel->priv->auto_hide_size);
3736
g_value_set_boolean (value, toplevel->priv->animate);
3738
case PROP_ANIMATION_SPEED:
3739
g_value_set_enum (value, toplevel->priv->animation_speed);
3741
case PROP_BUTTONS_ENABLED:
3742
g_value_set_boolean (value, toplevel->priv->buttons_enabled);
3744
case PROP_ARROWS_ENABLED:
3745
g_value_set_boolean (value, toplevel->priv->arrows_enabled);
3748
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3754
panel_toplevel_finalize (GObject *object)
3756
PanelToplevel *toplevel = (PanelToplevel *) object;
3758
panel_struts_unregister_strut (toplevel);
3760
toplevel_list = g_slist_remove (toplevel_list, toplevel);
3762
panel_toplevel_disconnect_gtk_settings (toplevel);
3763
toplevel->priv->gtk_settings = NULL;
3765
if (toplevel->priv->description)
3766
g_free (toplevel->priv->description);
3767
toplevel->priv->description = NULL;
3769
if (toplevel->priv->name)
3770
g_free (toplevel->priv->name);
3771
toplevel->priv->name = NULL;
3773
if (toplevel->priv->apply_delayed_id)
3774
g_source_remove (toplevel->priv->apply_delayed_id);
3775
toplevel->priv->apply_delayed_id = 0;
3777
if (toplevel->priv->delayed_settings) {
3778
g_settings_apply (toplevel->priv->delayed_settings);
3779
g_object_unref (toplevel->priv->delayed_settings);
3781
toplevel->priv->delayed_settings= NULL;
3783
if (toplevel->priv->settings)
3784
g_object_unref (toplevel->priv->settings);
3785
toplevel->priv->settings= NULL;
3787
if (toplevel->priv->settings_path)
3788
g_free (toplevel->priv->settings_path);
3789
toplevel->priv->settings_path = NULL;
3791
if (toplevel->priv->toplevel_id)
3792
g_free (toplevel->priv->toplevel_id);
3793
toplevel->priv->toplevel_id = NULL;
3795
G_OBJECT_CLASS (panel_toplevel_parent_class)->finalize (object);
3799
panel_toplevel_class_init (PanelToplevelClass *klass)
3801
GObjectClass *gobject_class = (GObjectClass *) klass;
3802
GtkWidgetClass *widget_class = (GtkWidgetClass *) klass;
3803
GtkContainerClass *container_class = (GtkContainerClass *) klass;
3804
GtkBindingSet *binding_set;
3806
binding_set = gtk_binding_set_by_class (klass);
3808
gobject_class->constructor = panel_toplevel_constructor;
3809
gobject_class->set_property = panel_toplevel_set_property;
3810
gobject_class->get_property = panel_toplevel_get_property;
3811
gobject_class->dispose = panel_toplevel_dispose;
3812
gobject_class->finalize = panel_toplevel_finalize;
3814
widget_class->realize = panel_toplevel_realize;
3815
widget_class->unrealize = panel_toplevel_unrealize;
3816
widget_class->get_preferred_width = panel_toplevel_get_preferred_width;
3817
widget_class->get_preferred_height = panel_toplevel_get_preferred_height;
3818
widget_class->size_allocate = panel_toplevel_size_allocate;
3819
widget_class->draw = panel_toplevel_draw;
3820
widget_class->button_press_event = panel_toplevel_button_press_event;
3821
widget_class->button_release_event = panel_toplevel_button_release_event;
3822
widget_class->key_press_event = panel_toplevel_key_press_event;
3823
widget_class->motion_notify_event = panel_toplevel_motion_notify_event;
3824
widget_class->enter_notify_event = panel_toplevel_enter_notify_event;
3825
widget_class->leave_notify_event = panel_toplevel_leave_notify_event;
3826
widget_class->screen_changed = panel_toplevel_screen_changed;
3827
widget_class->focus_in_event = panel_toplevel_focus_in_event;
3828
widget_class->focus_out_event = panel_toplevel_focus_out_event;
3829
widget_class->style_updated = panel_toplevel_style_updated;
3831
container_class->check_resize = panel_toplevel_check_resize;
3833
klass->hiding = NULL;
3834
klass->unhiding = NULL;
3835
klass->popup_panel_menu = panel_toplevel_popup_panel_menu;
3836
klass->toggle_expand = panel_toplevel_toggle_expand;
3837
klass->expand = panel_toplevel_expand;
3838
klass->unexpand = panel_toplevel_unexpand;
3839
klass->toggle_hidden = panel_toplevel_toggle_hidden;
3840
klass->begin_move = panel_toplevel_begin_move;
3841
klass->begin_resize = panel_toplevel_begin_resize;
3843
g_type_class_add_private (klass, sizeof (PanelToplevelPrivate));
3845
g_object_class_install_property (
3848
g_param_spec_string (
3851
"Unique identifier of this panel",
3853
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
3855
g_object_class_install_property (
3858
g_param_spec_string (
3861
"The GSettings path used for this panel",
3863
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
3865
g_object_class_install_property (
3868
g_param_spec_string (
3871
"The name of this panel",
3873
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3875
g_object_class_install_property (
3878
g_param_spec_boolean (
3881
"Expand to take up the full monitor width/height",
3883
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3885
g_object_class_install_property (
3891
"The orientation of the panel",
3892
PANEL_TYPE_ORIENTATION,
3893
PANEL_ORIENTATION_TOP,
3894
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3896
g_object_class_install_property (
3902
"The height (or width when vertical) of the panel",
3906
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3909
g_object_class_install_property (
3915
"The X position of the panel",
3919
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3921
g_object_class_install_property (
3926
"X position, from the right",
3927
"The X position of the panel, starting from the right of the screen",
3931
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3933
g_object_class_install_property (
3936
g_param_spec_boolean (
3939
"The x co-ordinate is relative to center screen",
3941
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3943
g_object_class_install_property (
3949
"The Y position of the panel",
3953
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3955
g_object_class_install_property (
3960
"Y position, from the bottom",
3961
"The Y position of the panel, starting from the bottom of the screen",
3965
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3967
g_object_class_install_property (
3970
g_param_spec_boolean (
3973
"The y co-ordinate is relative to center screen",
3975
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3977
g_object_class_install_property (
3983
"The monitor (in terms of Xinerama) which the panel is on",
3987
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3989
g_object_class_install_property (
3992
g_param_spec_boolean (
3995
"Automatically hide the panel when the mouse leaves the panel",
3997
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
3999
g_object_class_install_property (
4005
"The number of milliseconds to delay before automatically hiding",
4009
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
4011
g_object_class_install_property (
4017
"The number of milliseconds to delay before automatically un-hiding",
4020
DEFAULT_UNHIDE_DELAY,
4021
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
4023
g_object_class_install_property (
4029
"The number of pixels visible when the panel has been automatically hidden",
4032
DEFAULT_AUTO_HIDE_SIZE,
4033
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
4035
g_object_class_install_property (
4038
g_param_spec_boolean (
4041
"Enable hiding/showing animations",
4045
g_object_class_install_property (
4047
PROP_ANIMATION_SPEED,
4051
"The speed at which to animate panel hiding/showing",
4052
PANEL_TYPE_ANIMATION_SPEED,
4053
PANEL_ANIMATION_MEDIUM,
4054
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
4056
g_object_class_install_property (
4058
PROP_BUTTONS_ENABLED,
4059
g_param_spec_boolean (
4062
"Enable hide/show buttons",
4064
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
4066
g_object_class_install_property (
4068
PROP_ARROWS_ENABLED,
4069
g_param_spec_boolean (
4072
"Enable arrows on hide/show buttons",
4074
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
4076
gtk_widget_class_install_style_property (
4081
"The size of the arrows on the hide/show buttons",
4087
toplevel_signals [HIDE_SIGNAL] =
4088
g_signal_new ("hiding",
4089
G_TYPE_FROM_CLASS (gobject_class),
4090
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
4091
G_STRUCT_OFFSET (PanelToplevelClass, hiding),
4094
g_cclosure_marshal_VOID__VOID,
4098
toplevel_signals [UNHIDE_SIGNAL] =
4099
g_signal_new ("unhiding",
4100
G_TYPE_FROM_CLASS (gobject_class),
4101
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
4102
G_STRUCT_OFFSET (PanelToplevelClass, unhiding),
4105
g_cclosure_marshal_VOID__VOID,
4109
toplevel_signals [POPUP_PANEL_MENU_SIGNAL] =
4110
g_signal_new ("popup-panel-menu",
4111
G_TYPE_FROM_CLASS (gobject_class),
4112
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4113
G_STRUCT_OFFSET (PanelToplevelClass, popup_panel_menu),
4116
panel_marshal_BOOLEAN__VOID,
4120
toplevel_signals [TOGGLE_EXPAND_SIGNAL] =
4121
g_signal_new ("toggle-expand",
4122
G_TYPE_FROM_CLASS (gobject_class),
4123
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4124
G_STRUCT_OFFSET (PanelToplevelClass, toggle_expand),
4127
panel_marshal_BOOLEAN__VOID,
4131
toplevel_signals [EXPAND_SIGNAL] =
4132
g_signal_new ("expand",
4133
G_TYPE_FROM_CLASS (gobject_class),
4134
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4135
G_STRUCT_OFFSET (PanelToplevelClass, expand),
4138
panel_marshal_BOOLEAN__VOID,
4142
toplevel_signals [UNEXPAND_SIGNAL] =
4143
g_signal_new ("unexpand",
4144
G_TYPE_FROM_CLASS (gobject_class),
4145
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4146
G_STRUCT_OFFSET (PanelToplevelClass, unexpand),
4149
panel_marshal_BOOLEAN__VOID,
4153
toplevel_signals [TOGGLE_HIDDEN_SIGNAL] =
4154
g_signal_new ("toggle-hidden",
4155
G_TYPE_FROM_CLASS (gobject_class),
4156
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4157
G_STRUCT_OFFSET (PanelToplevelClass, toggle_hidden),
4160
panel_marshal_BOOLEAN__VOID,
4164
toplevel_signals [BEGIN_MOVE_SIGNAL] =
4165
g_signal_new ("begin-move",
4166
G_TYPE_FROM_CLASS (gobject_class),
4167
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4168
G_STRUCT_OFFSET (PanelToplevelClass, begin_move),
4171
panel_marshal_BOOLEAN__VOID,
4175
toplevel_signals [BEGIN_RESIZE_SIGNAL] =
4176
g_signal_new ("begin-resize",
4177
G_TYPE_FROM_CLASS (gobject_class),
4178
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
4179
G_STRUCT_OFFSET (PanelToplevelClass, begin_resize),
4182
panel_marshal_BOOLEAN__VOID,
4186
gtk_binding_entry_add_signal (binding_set, GDK_KEY_F10, GDK_CONTROL_MASK,
4187
"popup_panel_menu", 0);
4189
panel_bindings_set_entries (binding_set);
4193
panel_toplevel_setup_widgets (PanelToplevel *toplevel)
4195
GtkWidget *container;
4197
toplevel->priv->table = gtk_table_new (3, 3, FALSE);
4199
toplevel->priv->hide_button_top =
4200
panel_toplevel_add_hide_button (toplevel, GTK_ARROW_UP, 1, 2, 0, 1);
4202
toplevel->priv->hide_button_bottom =
4203
panel_toplevel_add_hide_button (toplevel, GTK_ARROW_DOWN, 1, 2, 2, 3);
4205
toplevel->priv->hide_button_left =
4206
panel_toplevel_add_hide_button (toplevel, GTK_ARROW_LEFT, 0, 1, 1, 2);
4208
toplevel->priv->hide_button_right =
4209
panel_toplevel_add_hide_button (toplevel, GTK_ARROW_RIGHT, 2, 3, 1, 2);
4211
if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
4212
gtk_widget_show (toplevel->priv->hide_button_left);
4213
gtk_widget_show (toplevel->priv->hide_button_right);
4215
gtk_widget_show (toplevel->priv->hide_button_top);
4216
gtk_widget_show (toplevel->priv->hide_button_bottom);
4219
toplevel->priv->inner_frame = g_object_new (PANEL_TYPE_FRAME, NULL);
4221
gtk_table_attach (GTK_TABLE (toplevel->priv->table),
4222
GTK_WIDGET (toplevel->priv->inner_frame),
4225
GTK_FILL | GTK_EXPAND | GTK_SHRINK,
4226
GTK_FILL | GTK_EXPAND | GTK_SHRINK,
4228
gtk_widget_show (GTK_WIDGET (toplevel->priv->inner_frame));
4230
container = panel_widget_new (toplevel,
4231
!toplevel->priv->expand,
4232
toplevel->priv->orientation & PANEL_HORIZONTAL_MASK ?
4233
GTK_ORIENTATION_HORIZONTAL :
4234
GTK_ORIENTATION_VERTICAL,
4235
toplevel->priv->size);
4237
toplevel->priv->panel_widget = PANEL_WIDGET (container);
4239
gtk_container_add (GTK_CONTAINER (toplevel->priv->inner_frame), container);
4240
gtk_widget_show (container);
4242
gtk_container_add (GTK_CONTAINER (toplevel), toplevel->priv->table);
4243
gtk_widget_show (toplevel->priv->table);
4248
panel_toplevel_init (PanelToplevel *toplevel)
4250
GtkStyleContext *context;
4252
toplevel->priv = PANEL_TOPLEVEL_GET_PRIVATE (toplevel);
4254
toplevel->priv->toplevel_id = NULL;
4256
toplevel->priv->settings_path = NULL;
4257
toplevel->priv->settings = NULL;
4258
toplevel->priv->delayed_settings = NULL;
4259
toplevel->priv->apply_delayed_id = 0;
4261
toplevel->priv->expand = TRUE;
4262
toplevel->priv->orientation = PANEL_ORIENTATION_BOTTOM;
4263
toplevel->priv->size = DEFAULT_SIZE;
4264
toplevel->priv->x = 0;
4265
toplevel->priv->y = 0;
4266
toplevel->priv->x_right = -1;
4267
toplevel->priv->y_bottom = -1;
4268
toplevel->priv->monitor = 0;
4269
toplevel->priv->configured_monitor = -1;
4270
toplevel->priv->hide_delay = DEFAULT_HIDE_DELAY;
4271
toplevel->priv->unhide_delay = DEFAULT_UNHIDE_DELAY;
4272
toplevel->priv->auto_hide_size = DEFAULT_AUTO_HIDE_SIZE;
4273
toplevel->priv->animation_speed = PANEL_ANIMATION_FAST;
4275
toplevel->priv->snap_tolerance = DEFAULT_DND_THRESHOLD * SNAP_TOLERANCE_FACTOR;
4276
toplevel->priv->gtk_settings = NULL;
4278
toplevel->priv->state = PANEL_STATE_NORMAL;
4280
toplevel->priv->name = NULL;
4281
toplevel->priv->description = NULL;
4283
toplevel->priv->hide_timeout = 0;
4284
toplevel->priv->unhide_timeout = 0;
4286
toplevel->priv->geometry.x = -1;
4287
toplevel->priv->geometry.y = -1;
4288
toplevel->priv->geometry.width = -1;
4289
toplevel->priv->geometry.height = -1;
4291
toplevel->priv->original_width = -1;
4292
toplevel->priv->original_height = -1;
4294
toplevel->priv->grab_op = PANEL_GRAB_OP_NONE;
4296
toplevel->priv->drag_offset_x = 0;
4297
toplevel->priv->drag_offset_y = 0;
4299
toplevel->priv->animation_end_x = 0;
4300
toplevel->priv->animation_end_y = 0;
4301
toplevel->priv->animation_end_width = 0;
4302
toplevel->priv->animation_end_height = 0;
4303
toplevel->priv->animation_start_time.tv_sec = 0;
4304
toplevel->priv->animation_start_time.tv_usec = 0;
4305
toplevel->priv->animation_end_time.tv_sec = 0;
4306
toplevel->priv->animation_end_time.tv_usec = 0;
4307
toplevel->priv->animation_timeout = 0;
4309
toplevel->priv->panel_widget = NULL;
4310
toplevel->priv->inner_frame = NULL;
4311
toplevel->priv->table = NULL;
4312
toplevel->priv->hide_button_top = NULL;
4313
toplevel->priv->hide_button_bottom = NULL;
4314
toplevel->priv->hide_button_left = NULL;
4315
toplevel->priv->hide_button_right = NULL;
4317
toplevel->priv->n_autohide_disablers = 0;
4319
toplevel->priv->auto_hide = FALSE;
4320
toplevel->priv->buttons_enabled = TRUE;
4321
toplevel->priv->arrows_enabled = TRUE;
4322
toplevel->priv->x_centered = FALSE;
4323
toplevel->priv->y_centered = FALSE;
4324
toplevel->priv->animating = FALSE;
4325
toplevel->priv->grab_is_keyboard = FALSE;
4326
toplevel->priv->position_centered = FALSE;
4327
toplevel->priv->updated_geometry_initial = FALSE;
4328
toplevel->priv->initial_animation_done = FALSE;
4330
gtk_widget_add_events (GTK_WIDGET (toplevel),
4331
GDK_BUTTON_PRESS_MASK |
4332
GDK_BUTTON_RELEASE_MASK |
4333
GDK_POINTER_MOTION_MASK |
4334
GDK_ENTER_NOTIFY_MASK |
4335
GDK_LEAVE_NOTIFY_MASK);
4337
panel_toplevel_setup_widgets (toplevel);
4338
panel_toplevel_update_description (toplevel);
4339
panel_toplevel_update_gtk_settings (toplevel);
4341
toplevel_list = g_slist_prepend (toplevel_list, toplevel);
4343
/* Prevent the window from being deleted via Alt+F4 by accident. This
4344
* happens with "alternative" window managers such as Sawfish or XFWM4.
4346
g_signal_connect (GTK_WIDGET (toplevel),
4348
G_CALLBACK (gtk_true),
4351
/* We don't want a resize grip on the panel */
4352
gtk_window_set_has_resize_grip (GTK_WINDOW (toplevel), FALSE);
4354
context = gtk_widget_get_style_context (GTK_WIDGET (toplevel));
4355
gtk_style_context_add_class (context, GTK_STYLE_CLASS_HORIZONTAL);
4359
panel_toplevel_get_panel_widget (PanelToplevel *toplevel)
4361
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), NULL);
4363
return toplevel->priv->panel_widget;
4367
panel_toplevel_position_is_writable (PanelToplevel *toplevel)
4369
if (panel_lockdown_get_panels_locked_down_s () ||
4370
!(g_settings_is_writable (toplevel->priv->settings,
4371
PANEL_TOPLEVEL_SCREEN_KEY) &&
4372
g_settings_is_writable (toplevel->priv->settings,
4373
PANEL_TOPLEVEL_MONITOR_KEY) &&
4374
g_settings_is_writable (toplevel->priv->settings,
4375
PANEL_TOPLEVEL_ORIENTATION_KEY)))
4378
/* For expanded panels we don't really have to check x and y */
4379
if (panel_toplevel_get_expand (toplevel))
4382
return (g_settings_is_writable (toplevel->priv->settings,
4383
PANEL_TOPLEVEL_X_KEY) &&
4384
g_settings_is_writable (toplevel->priv->settings,
4385
PANEL_TOPLEVEL_Y_KEY) &&
4386
g_settings_is_writable (toplevel->priv->settings,
4387
PANEL_TOPLEVEL_X_RIGHT_KEY) &&
4388
g_settings_is_writable (toplevel->priv->settings,
4389
PANEL_TOPLEVEL_Y_BOTTOM_KEY) &&
4390
g_settings_is_writable (toplevel->priv->settings,
4391
PANEL_TOPLEVEL_X_CENTERED_KEY) &&
4392
g_settings_is_writable (toplevel->priv->settings,
4393
PANEL_TOPLEVEL_Y_CENTERED_KEY));
4397
panel_toplevel_apply_delayed_settings (PanelToplevel *toplevel)
4399
g_settings_apply (toplevel->priv->delayed_settings);
4401
toplevel->priv->apply_delayed_id = 0;
4407
panel_toplevel_apply_delayed_settings_queue (PanelToplevel *toplevel)
4409
if (toplevel->priv->apply_delayed_id != 0)
4412
toplevel->priv->apply_delayed_id = g_timeout_add (500,
4413
(GSourceFunc) panel_toplevel_apply_delayed_settings,
4418
panel_toplevel_settings_bind_get_screen (GValue *value,
4422
PanelToplevel *toplevel = PANEL_TOPLEVEL (user_data);
4423
GdkDisplay *display;
4427
display = gdk_display_get_default ();
4428
screen_n = g_variant_get_int32 (variant);
4430
if (screen_n < 0 || screen_n >= gdk_display_get_n_screens (display)) {
4431
/* Trigger an event so that the gsettings key gets updated, to
4432
* to set the key back to an actual available screen so it will
4433
* get loaded on next startup. */
4434
g_object_notify (G_OBJECT (toplevel), "screen");
4438
screen = gdk_display_get_screen (display, screen_n);
4441
g_value_set_object (value, screen);
4443
return (screen != NULL);
4447
panel_toplevel_settings_bind_set_screen (const GValue *value,
4448
const GVariantType *expected_type,
4451
GdkScreen *screen = g_value_get_object (value);
4453
if (!screen || !GDK_IS_SCREEN (screen))
4454
screen = gdk_screen_get_default ();
4456
return g_variant_new ("i", gdk_screen_get_number (screen));
4460
panel_toplevel_bind_gsettings (PanelToplevel *toplevel)
4462
/* Delayed settings: the ones related to the position */
4464
g_settings_bind (toplevel->priv->delayed_settings,
4465
PANEL_TOPLEVEL_MONITOR_KEY,
4468
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4470
g_settings_bind (toplevel->priv->delayed_settings,
4471
PANEL_TOPLEVEL_SIZE_KEY,
4474
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4476
g_settings_bind (toplevel->priv->delayed_settings,
4477
PANEL_TOPLEVEL_ORIENTATION_KEY,
4480
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4482
g_settings_bind (toplevel->priv->delayed_settings,
4483
PANEL_TOPLEVEL_X_KEY,
4486
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4488
g_settings_bind (toplevel->priv->delayed_settings,
4489
PANEL_TOPLEVEL_X_RIGHT_KEY,
4492
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4494
g_settings_bind (toplevel->priv->delayed_settings,
4495
PANEL_TOPLEVEL_X_CENTERED_KEY,
4498
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4500
g_settings_bind (toplevel->priv->delayed_settings,
4501
PANEL_TOPLEVEL_Y_KEY,
4504
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4506
g_settings_bind (toplevel->priv->delayed_settings,
4507
PANEL_TOPLEVEL_Y_BOTTOM_KEY,
4510
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4512
g_settings_bind (toplevel->priv->delayed_settings,
4513
PANEL_TOPLEVEL_Y_CENTERED_KEY,
4516
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4518
/* Normal settings */
4520
g_settings_bind_with_mapping (toplevel->priv->settings,
4521
PANEL_TOPLEVEL_SCREEN_KEY,
4524
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY,
4525
panel_toplevel_settings_bind_get_screen,
4526
panel_toplevel_settings_bind_set_screen,
4529
g_settings_bind (toplevel->priv->settings,
4530
PANEL_TOPLEVEL_NAME_KEY,
4533
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4535
g_settings_bind (toplevel->priv->settings,
4536
PANEL_TOPLEVEL_EXPAND_KEY,
4539
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4541
g_settings_bind (toplevel->priv->settings,
4542
PANEL_TOPLEVEL_AUTO_HIDE_KEY,
4545
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4547
g_settings_bind (toplevel->priv->settings,
4548
PANEL_TOPLEVEL_HIDE_DELAY_KEY,
4551
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4553
g_settings_bind (toplevel->priv->settings,
4554
PANEL_TOPLEVEL_UNHIDE_DELAY_KEY,
4557
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4559
g_settings_bind (toplevel->priv->settings,
4560
PANEL_TOPLEVEL_AUTO_HIDE_SIZE_KEY,
4563
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4565
g_settings_bind (toplevel->priv->settings,
4566
PANEL_TOPLEVEL_ANIMATION_SPEED_KEY,
4569
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4571
g_settings_bind (toplevel->priv->settings,
4572
PANEL_TOPLEVEL_ENABLE_BUTTONS_KEY,
4575
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4577
g_settings_bind (toplevel->priv->settings,
4578
PANEL_TOPLEVEL_ENABLE_ARROWS_KEY,
4581
G_SETTINGS_BIND_DEFAULT|G_SETTINGS_BIND_NO_SENSITIVITY);
4585
panel_toplevel_set_toplevel_id (PanelToplevel *toplevel,
4586
const char *toplevel_id)
4588
g_assert (toplevel->priv->toplevel_id == NULL);
4590
toplevel->priv->toplevel_id = g_strdup (toplevel_id);
4594
panel_toplevel_get_id (PanelToplevel *toplevel)
4596
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), NULL);
4598
return toplevel->priv->toplevel_id;
4602
panel_toplevel_set_settings_path (PanelToplevel *toplevel,
4603
const char *settings_path)
4605
GSettings *settings_background;
4607
g_assert (toplevel->priv->settings_path == NULL);
4608
g_assert (toplevel->priv->settings == NULL);
4609
g_assert (toplevel->priv->delayed_settings == NULL);
4611
toplevel->priv->settings_path = g_strdup (settings_path);
4612
toplevel->priv->settings = g_settings_new_with_path (PANEL_TOPLEVEL_SCHEMA,
4614
toplevel->priv->delayed_settings = g_settings_new_with_path (PANEL_TOPLEVEL_SCHEMA,
4616
g_settings_delay (toplevel->priv->delayed_settings);
4618
settings_background = g_settings_get_child (toplevel->priv->settings,
4619
PANEL_BACKGROUND_SCHEMA_CHILD);
4620
/* FIXME: ideally, move this inside panel-widget.c since we're not
4621
* supposed to know about the backgrounds here */
4622
panel_background_settings_init (&toplevel->priv->panel_widget->background,
4623
settings_background);
4624
g_object_unref (settings_background);
4628
panel_toplevel_update_name (PanelToplevel *toplevel)
4632
g_assert (toplevel->priv->description != NULL);
4634
title = toplevel->priv->name ? toplevel->priv->name : toplevel->priv->description;
4636
gtk_window_set_title (GTK_WINDOW (toplevel), title);
4638
panel_a11y_set_atk_name_desc (
4639
GTK_WIDGET (toplevel->priv->panel_widget),
4640
title, toplevel->priv->description);
4644
panel_toplevel_set_name (PanelToplevel *toplevel,
4647
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
4649
if (!toplevel->priv->name && (!name || !name [0]))
4652
if (toplevel->priv->name && name && name [0] &&
4653
!strcmp (toplevel->priv->name, name))
4656
if (toplevel->priv->name)
4657
g_free (toplevel->priv->name);
4658
toplevel->priv->name = NULL;
4660
if (name && name [0])
4661
toplevel->priv->name = g_strdup (name);
4663
panel_toplevel_update_name (toplevel);
4665
g_object_notify (G_OBJECT (toplevel), "name");
4669
panel_toplevel_get_name (PanelToplevel *toplevel)
4671
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), NULL);
4673
return toplevel->priv->name;
4677
panel_toplevel_get_description (PanelToplevel *toplevel)
4679
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), NULL);
4681
return toplevel->priv->description;
4685
panel_toplevel_set_expand (PanelToplevel *toplevel,
4688
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
4690
expand = expand != FALSE;
4692
if (toplevel->priv->expand == expand)
4695
toplevel->priv->expand = expand;
4697
if (!toplevel->priv->expand &&
4698
toplevel->priv->updated_geometry_initial) {
4699
switch (toplevel->priv->orientation) {
4700
case PANEL_ORIENTATION_TOP:
4701
panel_toplevel_set_x (toplevel, 0, -1, TRUE);
4703
case PANEL_ORIENTATION_BOTTOM:
4704
panel_toplevel_set_x (toplevel, 0, 0, TRUE);
4706
case PANEL_ORIENTATION_LEFT:
4707
panel_toplevel_set_y (toplevel, 0, -1, TRUE);
4709
case PANEL_ORIENTATION_RIGHT:
4710
panel_toplevel_set_y (toplevel, 0, 0, TRUE);
4713
g_assert_not_reached ();
4718
gtk_widget_queue_resize (GTK_WIDGET (toplevel));
4720
panel_widget_set_packed (toplevel->priv->panel_widget, !toplevel->priv->expand);
4722
g_object_notify (G_OBJECT (toplevel), "expand");
4726
panel_toplevel_get_expand (PanelToplevel *toplevel)
4728
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), TRUE);
4730
return toplevel->priv->expand;
4734
panel_toplevel_get_is_floating (PanelToplevel *toplevel)
4736
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), TRUE);
4738
return toplevel->priv->floating;
4742
panel_toplevel_set_orientation (PanelToplevel *toplevel,
4743
PanelOrientation orientation)
4748
GtkStyleContext *context;
4750
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
4752
if (toplevel->priv->orientation == orientation)
4755
g_object_freeze_notify (G_OBJECT (toplevel));
4757
panel_toplevel_get_monitor_geometry (
4758
toplevel, NULL, NULL, &monitor_width, &monitor_height);
4760
/* Un-snap from center if no longer along screen edge */
4761
if (toplevel->priv->x_centered &&
4762
(orientation & PANEL_VERTICAL_MASK)) {
4763
toplevel->priv->x_centered = FALSE;
4764
toplevel->priv->x = (monitor_width - toplevel->priv->geometry.width) / 2;
4765
g_object_notify (G_OBJECT (toplevel), "x");
4766
g_object_notify (G_OBJECT (toplevel), "x-centered");
4768
if (toplevel->priv->x_right != -1) {
4769
toplevel->priv->x_right = -1;
4770
g_object_notify (G_OBJECT (toplevel), "x-right");
4774
if (toplevel->priv->y_centered &&
4775
(orientation & PANEL_HORIZONTAL_MASK)) {
4776
toplevel->priv->y_centered = FALSE;
4777
toplevel->priv->y = (monitor_height - toplevel->priv->geometry.height) / 2;
4778
g_object_notify (G_OBJECT (toplevel), "y");
4779
g_object_notify (G_OBJECT (toplevel), "y-centered");
4781
if (toplevel->priv->y_bottom != -1) {
4782
toplevel->priv->y_bottom = -1;
4783
g_object_notify (G_OBJECT (toplevel), "y-bottom");
4788
if ((orientation & PANEL_HORIZONTAL_MASK) &&
4789
(toplevel->priv->orientation & PANEL_VERTICAL_MASK))
4791
else if ((orientation & PANEL_VERTICAL_MASK) &&
4792
(toplevel->priv->orientation & PANEL_HORIZONTAL_MASK))
4795
/* rotate around the center */
4796
if (rotate && !toplevel->priv->position_centered && !toplevel->priv->expand &&
4797
toplevel->priv->updated_geometry_initial) {
4798
toplevel->priv->position_centered = TRUE;
4800
/* x, y temporary refer to the panel center, so we don't care
4801
* about x_right, y_bottom. Those will get updated in
4802
* panel_toplevel_update_position() accordingly. */
4803
if (!toplevel->priv->x_centered) {
4804
toplevel->priv->x += toplevel->priv->geometry.width / 2;
4805
g_object_notify (G_OBJECT (toplevel), "x");
4808
if (!toplevel->priv->y_centered) {
4809
toplevel->priv->y += toplevel->priv->geometry.height / 2;
4810
g_object_notify (G_OBJECT (toplevel), "y");
4815
toplevel->priv->orientation = orientation;
4817
context = gtk_widget_get_style_context (GTK_WIDGET (toplevel));
4818
if (orientation & PANEL_HORIZONTAL_MASK) {
4819
gtk_style_context_add_class (context, GTK_STYLE_CLASS_HORIZONTAL);
4820
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_VERTICAL);
4822
gtk_style_context_add_class (context, GTK_STYLE_CLASS_VERTICAL);
4823
gtk_style_context_remove_class (context, GTK_STYLE_CLASS_HORIZONTAL);
4825
gtk_widget_reset_style (GTK_WIDGET (toplevel));
4827
panel_toplevel_update_hide_buttons (toplevel);
4829
panel_widget_set_orientation (
4830
toplevel->priv->panel_widget,
4831
toplevel->priv->orientation & PANEL_HORIZONTAL_MASK ?
4832
GTK_ORIENTATION_HORIZONTAL :
4833
GTK_ORIENTATION_VERTICAL);
4835
switch (toplevel->priv->state) {
4836
case PANEL_STATE_HIDDEN_UP:
4837
if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
4838
toplevel->priv->state = PANEL_STATE_HIDDEN_LEFT;
4840
case PANEL_STATE_HIDDEN_DOWN:
4841
if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
4842
toplevel->priv->state = PANEL_STATE_HIDDEN_RIGHT;
4844
case PANEL_STATE_HIDDEN_LEFT:
4845
if (toplevel->priv->orientation & PANEL_VERTICAL_MASK)
4846
toplevel->priv->state = PANEL_STATE_HIDDEN_UP;
4848
case PANEL_STATE_HIDDEN_RIGHT:
4849
if (toplevel->priv->orientation & PANEL_VERTICAL_MASK)
4850
toplevel->priv->state = PANEL_STATE_HIDDEN_DOWN;
4856
gtk_widget_queue_resize (GTK_WIDGET (toplevel));
4858
panel_toplevel_apply_delayed_settings_queue (toplevel);
4859
g_object_notify (G_OBJECT (toplevel), "orientation");
4861
g_object_thaw_notify (G_OBJECT (toplevel));
4865
panel_toplevel_get_orientation (PanelToplevel *toplevel)
4867
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), GTK_ORIENTATION_HORIZONTAL);
4869
return toplevel->priv->orientation;
4873
panel_toplevel_set_size (PanelToplevel *toplevel,
4876
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
4877
g_return_if_fail (size >= 0);
4879
if (toplevel->priv->size == size)
4882
toplevel->priv->size = size;
4884
panel_widget_set_size (toplevel->priv->panel_widget, toplevel->priv->size);
4886
gtk_widget_queue_resize (GTK_WIDGET (toplevel));
4888
panel_toplevel_apply_delayed_settings_queue (toplevel);
4889
g_object_notify (G_OBJECT (toplevel), "size");
4893
panel_toplevel_get_size (PanelToplevel *toplevel)
4895
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), DEFAULT_SIZE);
4897
return toplevel->priv->size;
4901
panel_toplevel_set_auto_hide_size (PanelToplevel *toplevel,
4904
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
4906
if (toplevel->priv->auto_hide_size == auto_hide_size)
4909
toplevel->priv->auto_hide_size = auto_hide_size;
4911
if (toplevel->priv->state == PANEL_STATE_AUTO_HIDDEN) {
4912
if (panel_toplevel_update_struts (toplevel, FALSE)) {
4913
if (toplevel->priv->animate) {
4914
panel_toplevel_unhide (toplevel);
4915
panel_toplevel_hide (toplevel, TRUE, -1);
4917
gtk_widget_queue_resize (GTK_WIDGET (toplevel));
4921
g_object_notify (G_OBJECT (toplevel), "auto-hide-size");
4925
panel_toplevel_get_auto_hide_size (PanelToplevel *toplevel)
4927
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), DEFAULT_AUTO_HIDE_SIZE);
4929
return toplevel->priv->auto_hide_size;
4933
panel_toplevel_set_x (PanelToplevel *toplevel,
4936
gboolean x_centered)
4938
gboolean changed = FALSE;
4940
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
4942
x_centered = x_centered != FALSE;
4944
g_object_freeze_notify (G_OBJECT (toplevel));
4946
if (toplevel->priv->x != x) {
4947
toplevel->priv->x = x;
4949
g_object_notify (G_OBJECT (toplevel), "x");
4952
if (toplevel->priv->x_right != x_right) {
4953
toplevel->priv->x_right = x_right;
4955
g_object_notify (G_OBJECT (toplevel), "x-right");
4958
if (toplevel->priv->x_centered != x_centered) {
4959
toplevel->priv->x_centered = x_centered;
4961
g_object_notify (G_OBJECT (toplevel), "x-centered");
4965
panel_toplevel_apply_delayed_settings_queue (toplevel);
4966
gtk_widget_queue_resize (GTK_WIDGET (toplevel));
4969
g_object_thaw_notify (G_OBJECT (toplevel));
4973
panel_toplevel_set_y (PanelToplevel *toplevel,
4976
gboolean y_centered)
4978
gboolean changed = FALSE;
4980
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
4982
y_centered = y_centered != FALSE;
4984
g_object_freeze_notify (G_OBJECT (toplevel));
4986
if (toplevel->priv->y != y) {
4987
toplevel->priv->y = y;
4989
g_object_notify (G_OBJECT (toplevel), "y");
4992
if (toplevel->priv->y_bottom != y_bottom) {
4993
toplevel->priv->y_bottom = y_bottom;
4995
g_object_notify (G_OBJECT (toplevel), "y-bottom");
4998
if (toplevel->priv->y_centered != y_centered) {
4999
toplevel->priv->y_centered = y_centered;
5001
g_object_notify (G_OBJECT (toplevel), "y-centered");
5005
panel_toplevel_apply_delayed_settings_queue (toplevel);
5006
gtk_widget_queue_resize (GTK_WIDGET (toplevel));
5009
g_object_thaw_notify (G_OBJECT (toplevel));
5013
panel_toplevel_get_position (PanelToplevel *toplevel,
5019
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
5022
*x = toplevel->priv->x;
5025
*y = toplevel->priv->y;
5028
*x_right = toplevel->priv->x_right;
5031
*y_bottom = toplevel->priv->y_bottom;
5035
panel_toplevel_get_x_centered (PanelToplevel *toplevel)
5037
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
5039
return toplevel->priv->x_centered;
5043
panel_toplevel_get_y_centered (PanelToplevel *toplevel)
5045
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
5047
return toplevel->priv->y_centered;
5051
* panel_toplevel_set_monitor_internal:
5053
* Sets the monitor of the toplevel, but only the internal state. We need to
5054
* make the difference between the internal state and the configuration of the
5055
* user because internal constraints might affect the monitor of the toplevel.
5057
* panel_toplevel_set_monitor_internal() won't update the configuration of the
5061
panel_toplevel_set_monitor_internal (PanelToplevel *toplevel,
5063
gboolean force_resize)
5065
if (toplevel->priv->monitor == monitor)
5068
toplevel->priv->monitor = monitor;
5071
gtk_widget_queue_resize (GTK_WIDGET (toplevel));
5075
* panel_toplevel_update_monitor:
5077
* Moves the toplevel to its configured monitor or the first one, if needed.
5078
* This generally happens when the configured monitor was non-existing before,
5079
* and it appeared at runtime, or if it was existing and disappeared.
5081
* This must only be called at the beginning of the size request of the
5082
* toplevel because it doesn't queue a size request.
5085
panel_toplevel_update_monitor (PanelToplevel *toplevel)
5089
screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
5091
/* If we were not using the configured monitor, can we use it now? */
5092
if ((toplevel->priv->configured_monitor != -1) &&
5093
(toplevel->priv->configured_monitor != toplevel->priv->monitor) &&
5094
toplevel->priv->configured_monitor < panel_multiscreen_monitors (screen)) {
5095
panel_toplevel_set_monitor_internal (toplevel,
5096
toplevel->priv->configured_monitor,
5099
/* else, can we still use the monitor we were using? */
5100
} else if (toplevel->priv->monitor >= panel_multiscreen_monitors (screen)) {
5101
panel_toplevel_set_monitor_internal (toplevel,
5108
panel_toplevel_set_monitor (PanelToplevel *toplevel,
5113
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
5115
if (toplevel->priv->configured_monitor == monitor)
5118
toplevel->priv->configured_monitor = monitor;
5120
/* Only use the configured monitor if it's existing. Else, we ignore
5121
* the non-existing monitor, and keep the old one. The main use case is
5122
* when logging in after having used a multiscreen environment.
5123
* We will put the panel on the monitor 0 for this session, and it will
5124
* move back to the right monitor next time. */
5125
screen = gtk_window_get_screen (GTK_WINDOW (toplevel));
5126
if (monitor < panel_multiscreen_monitors (screen))
5127
panel_toplevel_set_monitor_internal (toplevel, monitor, TRUE);
5129
panel_toplevel_apply_delayed_settings_queue (toplevel);
5130
g_object_notify (G_OBJECT (toplevel), "monitor");
5134
panel_toplevel_get_monitor (PanelToplevel *toplevel)
5136
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), -1);
5138
return toplevel->priv->monitor;
5142
panel_toplevel_set_auto_hide (PanelToplevel *toplevel,
5145
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
5147
auto_hide = auto_hide != FALSE;
5149
if (toplevel->priv->auto_hide == auto_hide)
5152
toplevel->priv->auto_hide = auto_hide;
5154
if (toplevel->priv->auto_hide)
5155
panel_toplevel_queue_auto_hide (toplevel);
5157
panel_toplevel_queue_auto_unhide (toplevel);
5159
if (panel_toplevel_update_struts (toplevel, FALSE))
5160
gtk_widget_queue_resize (GTK_WIDGET (toplevel));
5162
g_object_notify (G_OBJECT (toplevel), "auto-hide");
5166
panel_toplevel_get_auto_hide (PanelToplevel *toplevel)
5168
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
5170
return toplevel->priv->auto_hide;
5174
panel_toplevel_set_hide_delay (PanelToplevel *toplevel,
5177
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
5179
if (toplevel->priv->hide_delay == hide_delay)
5182
toplevel->priv->hide_delay = hide_delay;
5184
g_object_notify (G_OBJECT (toplevel), "hide-delay");
5188
panel_toplevel_get_hide_delay (PanelToplevel *toplevel)
5190
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), -1);
5192
return toplevel->priv->hide_delay;
5196
panel_toplevel_set_unhide_delay (PanelToplevel *toplevel,
5199
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
5201
if (toplevel->priv->unhide_delay == unhide_delay)
5204
toplevel->priv->unhide_delay = unhide_delay;
5206
g_object_notify (G_OBJECT (toplevel), "unhide-delay");
5210
panel_toplevel_get_unhide_delay (PanelToplevel *toplevel)
5212
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), -1);
5214
return toplevel->priv->unhide_delay;
5218
panel_toplevel_set_animate (PanelToplevel *toplevel,
5221
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
5223
animate = animate != FALSE;
5225
if (toplevel->priv->animate == animate)
5228
toplevel->priv->animate = animate;
5230
g_object_notify (G_OBJECT (toplevel), "animate");
5234
panel_toplevel_get_animate (PanelToplevel *toplevel)
5236
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
5238
return toplevel->priv->animate;
5242
panel_toplevel_set_animation_speed (PanelToplevel *toplevel,
5243
PanelAnimationSpeed animation_speed)
5245
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
5247
if (toplevel->priv->animation_speed == animation_speed)
5250
toplevel->priv->animation_speed = animation_speed;
5252
g_object_notify (G_OBJECT (toplevel), "animation-speed");
5256
panel_toplevel_get_animation_speed (PanelToplevel *toplevel)
5258
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), 0);
5260
return toplevel->priv->animation_speed;
5264
panel_toplevel_set_enable_buttons (PanelToplevel *toplevel,
5265
gboolean enable_buttons)
5267
enable_buttons = enable_buttons != FALSE;
5269
if (toplevel->priv->buttons_enabled == enable_buttons)
5272
toplevel->priv->buttons_enabled = enable_buttons;
5274
panel_toplevel_update_hide_buttons (toplevel);
5276
g_object_notify (G_OBJECT (toplevel), "buttons-enabled");
5280
panel_toplevel_get_enable_buttons (PanelToplevel *toplevel)
5282
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
5284
return toplevel->priv->buttons_enabled;
5288
panel_toplevel_set_enable_arrows (PanelToplevel *toplevel,
5289
gboolean enable_arrows)
5291
g_return_if_fail (PANEL_IS_TOPLEVEL (toplevel));
5293
enable_arrows = enable_arrows != FALSE;
5295
if (toplevel->priv->arrows_enabled == enable_arrows)
5298
toplevel->priv->arrows_enabled = enable_arrows;
5300
panel_toplevel_update_hide_buttons (toplevel);
5302
g_object_notify (G_OBJECT (toplevel), "arrows-enabled");
5306
panel_toplevel_get_enable_arrows (PanelToplevel *toplevel)
5308
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
5310
return toplevel->priv->arrows_enabled;
5314
panel_toplevel_rotate (PanelToplevel *toplevel,
5317
PanelOrientation orientation;
5319
/* Relies on PanelOrientation definition:
5322
* PANEL_ORIENTATION_TOP = 1 << 0,
5323
* PANEL_ORIENTATION_RIGHT = 1 << 1,
5324
* PANEL_ORIENTATION_BOTTOM = 1 << 2,
5325
* PANEL_ORIENTATION_LEFT = 1 << 3
5326
* } PanelOrientation;
5329
orientation = toplevel->priv->orientation;
5336
if (orientation == 0)
5337
orientation = PANEL_ORIENTATION_LEFT;
5339
else if (orientation > PANEL_ORIENTATION_LEFT)
5340
orientation = PANEL_ORIENTATION_TOP;
5342
panel_toplevel_set_orientation (toplevel, orientation);
5346
panel_toplevel_get_state (PanelToplevel *toplevel)
5348
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), 0);
5350
return toplevel->priv->state;
5354
panel_toplevel_get_is_hidden (PanelToplevel *toplevel)
5356
g_return_val_if_fail (PANEL_IS_TOPLEVEL (toplevel), FALSE);
5358
if (toplevel->priv->state == PANEL_STATE_HIDDEN_UP ||
5359
toplevel->priv->state == PANEL_STATE_HIDDEN_DOWN ||
5360
toplevel->priv->state == PANEL_STATE_HIDDEN_LEFT ||
5361
toplevel->priv->state == PANEL_STATE_HIDDEN_RIGHT)
5368
panel_toplevel_get_minimum_size (PanelToplevel *toplevel)
5370
return calculate_minimum_height (GTK_WIDGET (toplevel),
5371
toplevel->priv->orientation);
5375
panel_toplevel_get_maximum_size (PanelToplevel *toplevel)
5377
int monitor_width, monitor_height;
5379
panel_toplevel_get_monitor_geometry (toplevel, NULL, NULL,
5380
&monitor_width, &monitor_height);
5382
if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK)
5383
return monitor_height / MAXIMUM_SIZE_SCREEN_RATIO;
5385
return monitor_width / MAXIMUM_SIZE_SCREEN_RATIO;