gtknotebook.c 251 KB
Newer Older
1
/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
Cody Russell's avatar
Cody Russell committed
2
/* GTK - The GIMP Toolkit
Elliot Lee's avatar
Elliot Lee committed
3 4 5
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
7 8 9 10 11 12
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
14
 *
15
 * You should have received a copy of the GNU Lesser General Public
16 17 18
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
Elliot Lee's avatar
Elliot Lee committed
19
 */
20 21

/*
22
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23 24
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
25
 * GTK+ at ftp:ftp.gtk.org/pub/gtk/.
26 27
 */

28
#include "config.h"
29 30

#include <stdio.h>
31
#include <string.h>
32

33
#include "gtknotebook.h"
34

35 36 37 38
#include "gtkmain.h"
#include "gtkmenu.h"
#include "gtkmenuitem.h"
#include "gtklabel.h"
39
#include "gtkintl.h"
40
#include "gtkmarshalers.h"
41
#include "gtkbindings.h"
42
#include "gtkprivate.h"
43
#include "gtkdnd.h"
44
#include "gtkbuildable.h"
45
#include "gtktypebuiltins.h"
46

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73

/**
 * SECTION:gtknotebook
 * @Short_description: A tabbed notebook container
 * @Title: GtkNotebook
 * @See_also: #GtkContainer
 *
 * The #GtkNotebook widget is a #GtkContainer whose children are pages that
 * can be switched between using tab labels along one edge.
 *
 * There are many configuration options for GtkNotebook. Among other
 * things, you can choose on which edge the tabs appear
 * (see gtk_notebook_set_tab_pos()), whether, if there are too many
 * tabs to fit the notebook should be made bigger or scrolling
 * arrows added (see gtk_notebook_set_scrollable()), and whether there
 * will be a popup menu allowing the users to switch pages.
 * (see gtk_notebook_popup_enable(), gtk_notebook_popup_disable())
 *
 * <refsect2 id="GtkNotebook-BUILDER-UI">
 * <title>GtkNotebook as GtkBuildable</title>
 * <para>
 * The GtkNotebook implementation of the #GtkBuildable interface
 * supports placing children into tabs by specifying "tab" as the
 * "type" attribute of a &lt;child&gt; element. Note that the content
 * of the tab must be created before the tab can be filled.
 * A tab child can be specified without specifying a &lt;child&gt;
 * type attribute.
74
 *
75 76 77
 * To add a child widget in the notebooks action area, specify
 * "action-start" or "action-end" as the "type" attribute of the &lt;child&gt;
 * element.
78
 * </para>
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
 * <example>
 * <title>A UI definition fragment with GtkNotebook</title>
 * <programlisting><![CDATA[
 * <object class="GtkNotebook">
 *   <child>
 *     <object class="GtkLabel" id="notebook-content">
 *       <property name="label">Content</property>
 *     </object>
 *   </child>
 *   <child type="tab">
 *     <object class="GtkLabel" id="notebook-tab">
 *       <property name="label">Tab</property>
 *     </object>
 *   </child>
 * </object>
 * ]]></programlisting>
 * </example>
 * </refsect2>
 */


100
#define SCROLL_DELAY_FACTOR   5
101 102
#define SCROLL_THRESHOLD      12
#define DND_THRESHOLD_MULTIPLIER 4
103 104
#define FRAMES_PER_SECOND     45
#define MSECS_BETWEEN_UPDATES (1000 / FRAMES_PER_SECOND)
Elliot Lee's avatar
Elliot Lee committed
105

106
typedef struct _GtkNotebookPage GtkNotebookPage;
107 108 109 110 111 112 113 114 115 116 117 118 119 120

typedef enum
{
  DRAG_OPERATION_NONE,
  DRAG_OPERATION_REORDER,
  DRAG_OPERATION_DETACH
} GtkNotebookDragOperation;

enum {
  ACTION_WIDGET_START,
  ACTION_WIDGET_END,
  N_ACTION_WIDGETS
};

121
struct _GtkNotebookPrivate
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
{
  GtkNotebookDragOperation   operation;
  GtkNotebookPage           *cur_page;
  GtkNotebookPage           *detached_tab;
  GtkTargetList             *source_targets;
  GtkWidget                 *action_widget[N_ACTION_WIDGETS];
  GtkWidget                 *dnd_window;
  GtkWidget                 *menu;

  GdkWindow               *drag_window;
  GdkWindow               *event_window;

  GList         *children;
  GList         *first_tab;             /* The first tab visible (for scrolling notebooks) */
  GList         *focus_tab;

  gint           drag_begin_x;
  gint           drag_begin_y;
  gint           drag_offset_x;
  gint           drag_offset_y;
  gint           drag_window_x;
  gint           drag_window_y;
  gint           mouse_x;
  gint           mouse_y;
  gint           pressed_button;

148
  GQuark         group;
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180

  guint          dnd_timer;
  guint          switch_tab_timer;

  guint16        tab_hborder;
  guint16        tab_vborder;

  guint32        timer;
  guint32        timestamp;

  guint          button             : 2;
  guint          child_has_focus    : 1;
  guint          click_child        : 3;
  guint          during_detach      : 1;
  guint          during_reorder     : 1;
  guint          focus_out          : 1; /* Flag used by ::move-focus-out implementation */
  guint          has_scrolled       : 1;
  guint          have_visible_child : 1;
  guint          homogeneous        : 1;
  guint          in_child           : 3;
  guint          need_timer         : 1;
  guint          show_border        : 1;
  guint          show_tabs          : 1;
  guint          scrollable         : 1;
  guint          tab_pos            : 2;

  guint          has_before_previous : 1;
  guint          has_before_next     : 1;
  guint          has_after_previous  : 1;
  guint          has_after_next      : 1;
};

181 182
enum {
  SWITCH_PAGE,
183 184
  FOCUS_TAB,
  SELECT_PAGE,
185
  CHANGE_CURRENT_PAGE,
186
  MOVE_FOCUS_OUT,
187
  REORDER_TAB,
188 189 190
  PAGE_REORDERED,
  PAGE_REMOVED,
  PAGE_ADDED,
191
  CREATE_WINDOW,
192 193 194
  LAST_SIGNAL
};

195 196 197 198 199
enum {
  STEP_PREV,
  STEP_NEXT
};

200 201 202 203 204 205 206 207 208
typedef enum
{
  ARROW_NONE,
  ARROW_LEFT_BEFORE,
  ARROW_RIGHT_BEFORE,
  ARROW_LEFT_AFTER,
  ARROW_RIGHT_AFTER
} GtkNotebookArrow;

209 210 211 212 213 214 215
typedef enum
{
  POINTER_BEFORE,
  POINTER_AFTER,
  POINTER_BETWEEN
} GtkNotebookPointerPosition;

216 217 218
#define ARROW_IS_LEFT(arrow)  ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_LEFT_AFTER)
#define ARROW_IS_BEFORE(arrow) ((arrow) == ARROW_LEFT_BEFORE || (arrow) == ARROW_RIGHT_BEFORE)

219
enum {
220 221 222 223 224 225 226
  PROP_0,
  PROP_TAB_POS,
  PROP_SHOW_TABS,
  PROP_SHOW_BORDER,
  PROP_SCROLLABLE,
  PROP_PAGE,
  PROP_ENABLE_POPUP,
227
  PROP_GROUP_NAME
228 229 230
};

enum {
Tim Janik's avatar
Tim Janik committed
231 232 233 234 235 236
  CHILD_PROP_0,
  CHILD_PROP_TAB_LABEL,
  CHILD_PROP_MENU_LABEL,
  CHILD_PROP_POSITION,
  CHILD_PROP_TAB_EXPAND,
  CHILD_PROP_TAB_FILL,
237 238
  CHILD_PROP_REORDERABLE,
  CHILD_PROP_DETACHABLE
239 240
};

241 242
#define GTK_NOTEBOOK_PAGE(_glist_)         ((GtkNotebookPage *)((GList *)(_glist_))->data)

243 244 245 246 247 248 249
/* some useful defines for calculating coords */
#define PAGE_LEFT_X(_page_)   (((GtkNotebookPage *) (_page_))->allocation.x)
#define PAGE_RIGHT_X(_page_)  (((GtkNotebookPage *) (_page_))->allocation.x + ((GtkNotebookPage *) (_page_))->allocation.width)
#define PAGE_MIDDLE_X(_page_) (((GtkNotebookPage *) (_page_))->allocation.x + ((GtkNotebookPage *) (_page_))->allocation.width / 2)
#define PAGE_TOP_Y(_page_)    (((GtkNotebookPage *) (_page_))->allocation.y)
#define PAGE_BOTTOM_Y(_page_) (((GtkNotebookPage *) (_page_))->allocation.y + ((GtkNotebookPage *) (_page_))->allocation.height)
#define PAGE_MIDDLE_Y(_page_) (((GtkNotebookPage *) (_page_))->allocation.y + ((GtkNotebookPage *) (_page_))->allocation.height / 2)
250
#define NOTEBOOK_IS_TAB_LABEL_PARENT(_notebook_,_page_) (gtk_widget_get_parent (((GtkNotebookPage *) (_page_))->tab_label) == ((GtkWidget *) (_notebook_)))
251

252 253 254 255 256
struct _GtkNotebookPage
{
  GtkWidget *child;
  GtkWidget *tab_label;
  GtkWidget *menu_label;
257
  GtkWidget *last_focus_child;  /* Last descendant of the page that had focus */
258

259 260
  guint default_menu : 1;       /* If true, we create the menu label ourself */
  guint default_tab  : 1;       /* If true, we create the tab label ourself */
261 262
  guint expand       : 1;
  guint fill         : 1;
263 264
  guint reorderable  : 1;
  guint detachable   : 1;
265

266 267 268 269 270
  /* if true, the tab label was visible on last allocation; we track this so
   * that we know to redraw the tab area if a tab label was hidden then shown
   * without changing position */
  guint tab_allocated_visible : 1;

271 272
  GtkRequisition requisition;
  GtkAllocation allocation;
273

274 275
  gulong mnemonic_activate_signal;
  gulong notify_visible_handler;
276 277
};

278
static const GtkTargetEntry notebook_targets [] = {
279
  { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, 0 },
280 281
};

282 283
#ifdef G_DISABLE_CHECKS
#define CHECK_FIND_CHILD(notebook, child)                           \
284
 gtk_notebook_find_child (notebook, child, G_STRLOC)
285 286
#else
#define CHECK_FIND_CHILD(notebook, child)                           \
287
 gtk_notebook_find_child (notebook, child, NULL)
288
#endif
289

290
/*** GtkNotebook Methods ***/
291
static gboolean gtk_notebook_select_page         (GtkNotebook      *notebook,
292
                                                  gboolean          move_focus);
293
static gboolean gtk_notebook_focus_tab           (GtkNotebook      *notebook,
294
                                                  GtkNotebookTab    type);
295
static gboolean gtk_notebook_change_current_page (GtkNotebook      *notebook,
296
                                                  gint              offset);
297
static void     gtk_notebook_move_focus_out      (GtkNotebook      *notebook,
298
                                                  GtkDirectionType  direction_type);
299
static gboolean gtk_notebook_reorder_tab         (GtkNotebook      *notebook,
300 301
                                                  GtkDirectionType  direction_type,
                                                  gboolean          move_to_last);
302
static void     gtk_notebook_remove_tab_label    (GtkNotebook      *notebook,
303
                                                  GtkNotebookPage  *page);
304 305 306
static void     gtk_notebook_set_tab_label_packing   (GtkNotebook  *notebook,
                                                      GtkWidget    *child,
                                                      gboolean      expand,
307
                                                      gboolean      fill);
308 309 310
static void     gtk_notebook_query_tab_label_packing (GtkNotebook  *notebook,
                                                      GtkWidget    *child,
                                                      gboolean     *expand,
311
                                                      gboolean     *fill);
312

313
/*** GObject Methods ***/
314 315 316 317 318 319 320 321
static void gtk_notebook_set_property        (GObject         *object,
                                              guint            prop_id,
                                              const GValue    *value,
                                              GParamSpec      *pspec);
static void gtk_notebook_get_property        (GObject         *object,
                                              guint            prop_id,
                                              GValue          *value,
                                              GParamSpec      *pspec);
322

323
/*** GtkWidget Methods ***/
324
static void gtk_notebook_destroy             (GtkWidget        *widget);
325 326 327
static void gtk_notebook_map                 (GtkWidget        *widget);
static void gtk_notebook_unmap               (GtkWidget        *widget);
static void gtk_notebook_realize             (GtkWidget        *widget);
328
static void gtk_notebook_unrealize           (GtkWidget        *widget);
329
static void gtk_notebook_size_request        (GtkWidget        *widget,
330
                                              GtkRequisition   *requisition);
331
static void gtk_notebook_get_preferred_width (GtkWidget        *widget,
332 333
                                              gint             *minimum,
                                              gint             *natural);
334
static void gtk_notebook_get_preferred_height(GtkWidget        *widget,
335 336
                                              gint             *minimum,
                                              gint             *natural);
337
static void gtk_notebook_size_allocate       (GtkWidget        *widget,
338
                                              GtkAllocation    *allocation);
339 340
static gint gtk_notebook_draw                (GtkWidget        *widget,
                                              cairo_t          *cr);
341
static gint gtk_notebook_button_press        (GtkWidget        *widget,
342
                                              GdkEventButton   *event);
343
static gint gtk_notebook_button_release      (GtkWidget        *widget,
344
                                              GdkEventButton   *event);
345
static gboolean gtk_notebook_popup_menu      (GtkWidget        *widget);
346
static gint gtk_notebook_leave_notify        (GtkWidget        *widget,
347
                                              GdkEventCrossing *event);
348
static gint gtk_notebook_motion_notify       (GtkWidget        *widget,
349
                                              GdkEventMotion   *event);
350
static gint gtk_notebook_focus_in            (GtkWidget        *widget,
351
                                              GdkEventFocus    *event);
352
static gint gtk_notebook_focus_out           (GtkWidget        *widget,
353
                                              GdkEventFocus    *event);
Matthias Clasen's avatar
Matthias Clasen committed
354
static void gtk_notebook_grab_notify         (GtkWidget          *widget,
355
                                              gboolean            was_grabbed);
356
static void gtk_notebook_state_flags_changed (GtkWidget          *widget,
357
                                              GtkStateFlags       previous_state);
358
static gint gtk_notebook_focus               (GtkWidget        *widget,
359
                                              GtkDirectionType  direction);
360
static void gtk_notebook_style_updated       (GtkWidget        *widget);
361

362 363
/*** Drag and drop Methods ***/
static void gtk_notebook_drag_begin          (GtkWidget        *widget,
364
                                              GdkDragContext   *context);
365
static void gtk_notebook_drag_end            (GtkWidget        *widget,
366
                                              GdkDragContext   *context);
367
static gboolean gtk_notebook_drag_failed     (GtkWidget        *widget,
368 369
                                              GdkDragContext   *context,
                                              GtkDragResult     result);
370
static gboolean gtk_notebook_drag_motion     (GtkWidget        *widget,
371 372 373 374
                                              GdkDragContext   *context,
                                              gint              x,
                                              gint              y,
                                              guint             time);
375
static void gtk_notebook_drag_leave          (GtkWidget        *widget,
376 377
                                              GdkDragContext   *context,
                                              guint             time);
378
static gboolean gtk_notebook_drag_drop       (GtkWidget        *widget,
379 380 381 382
                                              GdkDragContext   *context,
                                              gint              x,
                                              gint              y,
                                              guint             time);
383
static void gtk_notebook_drag_data_get       (GtkWidget        *widget,
384 385 386 387
                                              GdkDragContext   *context,
                                              GtkSelectionData *data,
                                              guint             info,
                                              guint             time);
388
static void gtk_notebook_drag_data_received  (GtkWidget        *widget,
389 390 391 392 393 394
                                              GdkDragContext   *context,
                                              gint              x,
                                              gint              y,
                                              GtkSelectionData *data,
                                              guint             info,
                                              guint             time);
395

396
/*** GtkContainer Methods ***/
Tim Janik's avatar
Tim Janik committed
397
static void gtk_notebook_set_child_property  (GtkContainer     *container,
398 399 400 401
                                              GtkWidget        *child,
                                              guint             property_id,
                                              const GValue     *value,
                                              GParamSpec       *pspec);
Tim Janik's avatar
Tim Janik committed
402
static void gtk_notebook_get_child_property  (GtkContainer     *container,
403 404 405 406
                                              GtkWidget        *child,
                                              guint             property_id,
                                              GValue           *value,
                                              GParamSpec       *pspec);
407
static void gtk_notebook_add                 (GtkContainer     *container,
408
                                              GtkWidget        *widget);
409
static void gtk_notebook_remove              (GtkContainer     *container,
410
                                              GtkWidget        *widget);
411
static void gtk_notebook_set_focus_child     (GtkContainer     *container,
412
                                              GtkWidget        *child);
Manish Singh's avatar
Manish Singh committed
413
static GType gtk_notebook_child_type       (GtkContainer     *container);
414
static void gtk_notebook_forall              (GtkContainer     *container,
415 416 417
                                              gboolean          include_internals,
                                              GtkCallback       callback,
                                              gpointer          callback_data);
418 419
static GtkWidgetPath * gtk_notebook_get_path_for_child (GtkContainer *container,
                                                        GtkWidget    *widget);
420

421 422
/*** GtkNotebook Methods ***/
static gint gtk_notebook_real_insert_page    (GtkNotebook      *notebook,
423 424 425 426
                                              GtkWidget        *child,
                                              GtkWidget        *tab_label,
                                              GtkWidget        *menu_label,
                                              gint              position);
427

428 429 430 431 432
static GtkNotebook *gtk_notebook_create_window (GtkNotebook    *notebook,
                                                GtkWidget      *page,
                                                gint            x,
                                                gint            y);

433
/*** GtkNotebook Private Functions ***/
434 435
static void gtk_notebook_redraw_tabs         (GtkNotebook      *notebook);
static void gtk_notebook_redraw_arrows       (GtkNotebook      *notebook);
436
static void gtk_notebook_real_remove         (GtkNotebook      *notebook,
437
                                              GList            *list);
438 439
static void gtk_notebook_update_labels       (GtkNotebook      *notebook);
static gint gtk_notebook_timer               (GtkNotebook      *notebook);
440
static void gtk_notebook_set_scroll_timer    (GtkNotebook *notebook);
441
static gint gtk_notebook_page_compare        (gconstpointer     a,
442
                                              gconstpointer     b);
443
static GList* gtk_notebook_find_child        (GtkNotebook      *notebook,
444 445
                                              GtkWidget        *child,
                                              const gchar      *function);
446
static GList * gtk_notebook_search_page      (GtkNotebook      *notebook,
447 448 449
                                              GList            *list,
                                              gint              direction,
                                              gboolean          find_visible);
450
static void  gtk_notebook_child_reordered    (GtkNotebook      *notebook,
451
                                              GtkNotebookPage  *page);
452

453
/*** GtkNotebook Drawing Functions ***/
454
static void gtk_notebook_paint               (GtkWidget        *widget,
455
                                              cairo_t          *cr);
456
static void gtk_notebook_draw_tab            (GtkNotebook      *notebook,
457 458
                                              GtkNotebookPage  *page,
                                              cairo_t          *cr,
459
                                              GtkRegionFlags    flags);
460
static void gtk_notebook_draw_arrow          (GtkNotebook      *notebook,
461
                                              cairo_t          *cr,
462
                                              GtkNotebookArrow  arrow);
463

464
/*** GtkNotebook Size Allocate Functions ***/
465
static void gtk_notebook_pages_allocate      (GtkNotebook      *notebook);
466
static gboolean gtk_notebook_page_allocate   (GtkNotebook      *notebook,
467
                                              GtkNotebookPage  *page);
468
static void gtk_notebook_calc_tabs           (GtkNotebook      *notebook,
469 470 471 472
                                              GList            *start,
                                              GList           **end,
                                              gint             *tab_space,
                                              guint             direction);
473

474
/*** GtkNotebook Page Switch Methods ***/
475
static void gtk_notebook_real_switch_page    (GtkNotebook      *notebook,
476 477
                                              GtkWidget        *child,
                                              guint             page_num);
478

479
/*** GtkNotebook Page Switch Functions ***/
480
static void gtk_notebook_switch_page         (GtkNotebook      *notebook,
481
                                              GtkNotebookPage  *page);
482
static gint gtk_notebook_page_select         (GtkNotebook      *notebook,
483
                                              gboolean          move_focus);
484 485
static void gtk_notebook_switch_focus_tab    (GtkNotebook      *notebook,
                                              GList            *new_child);
486
static void gtk_notebook_menu_switch_page    (GtkWidget        *widget,
487
                                              GtkNotebookPage  *page);
488

489
/*** GtkNotebook Menu Functions ***/
490
static void gtk_notebook_menu_item_create    (GtkNotebook      *notebook,
491
                                              GList            *list);
492
static void gtk_notebook_menu_label_unparent (GtkWidget        *widget,
493
                                              gpointer          data);
494
static void gtk_notebook_menu_detacher       (GtkWidget        *widget,
495
                                              GtkMenu          *menu);
496

497
/*** GtkNotebook Private Setters ***/
498 499
static void gtk_notebook_update_tab_states             (GtkNotebook *notebook);
static gboolean gtk_notebook_mnemonic_activate_switch_page (GtkWidget *child,
500 501
                                                            gboolean overload,
                                                            gpointer data);
502

503 504
static gboolean focus_tabs_in  (GtkNotebook      *notebook);
static gboolean focus_child_in (GtkNotebook      *notebook,
505
                                GtkDirectionType  direction);
Elliot Lee's avatar
Elliot Lee committed
506

507
static void stop_scrolling (GtkNotebook *notebook);
508
static void do_detach_tab  (GtkNotebook *from,
509 510 511 512
                            GtkNotebook *to,
                            GtkWidget   *child,
                            gint         x,
                            gint         y);
513

514 515
/* GtkBuildable */
static void gtk_notebook_buildable_init           (GtkBuildableIface *iface);
516
static void gtk_notebook_buildable_add_child      (GtkBuildable *buildable,
517 518 519
                                                   GtkBuilder   *builder,
                                                   GObject      *child,
                                                   const gchar  *type);
520

521
static guint notebook_signals[LAST_SIGNAL] = { 0 };
Elliot Lee's avatar
Elliot Lee committed
522

523
G_DEFINE_TYPE_WITH_CODE (GtkNotebook, gtk_notebook, GTK_TYPE_CONTAINER,
524 525
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                gtk_notebook_buildable_init))
Elliot Lee's avatar
Elliot Lee committed
526

527 528
static void
add_tab_bindings (GtkBindingSet    *binding_set,
529 530
                  GdkModifierType   modifiers,
                  GtkDirectionType  direction)
531
{
532
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_Tab, modifiers,
533 534
                                "move_focus_out", 1,
                                GTK_TYPE_DIRECTION_TYPE, direction);
535
  gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_Tab, modifiers,
536 537 538 539 540 541
                                "move_focus_out", 1,
                                GTK_TYPE_DIRECTION_TYPE, direction);
}

static void
add_arrow_bindings (GtkBindingSet    *binding_set,
542 543
                    guint             keysym,
                    GtkDirectionType  direction)
544
{
545
  guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
546

547 548 549 550 551 552 553 554
  gtk_binding_entry_add_signal (binding_set, keysym, GDK_CONTROL_MASK,
                                "move_focus_out", 1,
                                GTK_TYPE_DIRECTION_TYPE, direction);
  gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_CONTROL_MASK,
                                "move_focus_out", 1,
                                GTK_TYPE_DIRECTION_TYPE, direction);
}

555 556
static void
add_reorder_bindings (GtkBindingSet    *binding_set,
557 558 559
                      guint             keysym,
                      GtkDirectionType  direction,
                      gboolean          move_to_last)
560
{
561
  guint keypad_keysym = keysym - GDK_KEY_Left + GDK_KEY_KP_Left;
562 563

  gtk_binding_entry_add_signal (binding_set, keysym, GDK_MOD1_MASK,
564 565 566
                                "reorder_tab", 2,
                                GTK_TYPE_DIRECTION_TYPE, direction,
                                G_TYPE_BOOLEAN, move_to_last);
567
  gtk_binding_entry_add_signal (binding_set, keypad_keysym, GDK_MOD1_MASK,
568 569 570
                                "reorder_tab", 2,
                                GTK_TYPE_DIRECTION_TYPE, direction,
                                G_TYPE_BOOLEAN, move_to_last);
571 572
}

573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
static gboolean
gtk_object_handled_accumulator (GSignalInvocationHint *ihint,
                                GValue                *return_accu,
                                const GValue          *handler_return,
                                gpointer               dummy)
{
  gboolean continue_emission;
  GObject *object;

  object = g_value_get_object (handler_return);
  g_value_set_object (return_accu, object);
  continue_emission = !object;

  return continue_emission;
}

589
static void
590 591 592
gtk_notebook_compute_expand (GtkWidget *widget,
                             gboolean  *hexpand_p,
                             gboolean  *vexpand_p)
593
{
594
  GtkNotebook *notebook = GTK_NOTEBOOK (widget);
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
  GtkNotebookPrivate *priv = notebook->priv;
  gboolean hexpand;
  gboolean vexpand;
  GList *list;
  GtkNotebookPage *page;

  hexpand = FALSE;
  vexpand = FALSE;

  for (list = priv->children; list; list = list->next)
    {
      page = list->data;

      hexpand = hexpand ||
        gtk_widget_compute_expand (page->child, GTK_ORIENTATION_HORIZONTAL);

      vexpand = vexpand ||
        gtk_widget_compute_expand (page->child, GTK_ORIENTATION_VERTICAL);

      if (hexpand & vexpand)
        break;
    }

  *hexpand_p = hexpand;
  *vexpand_p = vexpand;
}

Elliot Lee's avatar
Elliot Lee committed
622 623 624
static void
gtk_notebook_class_init (GtkNotebookClass *class)
{
Tim Janik's avatar
Tim Janik committed
625 626 627
  GObjectClass   *gobject_class = G_OBJECT_CLASS (class);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
628
  GtkBindingSet *binding_set;
629

630 631
  gobject_class->set_property = gtk_notebook_set_property;
  gobject_class->get_property = gtk_notebook_get_property;
632

633
  widget_class->destroy = gtk_notebook_destroy;
Elliot Lee's avatar
Elliot Lee committed
634 635 636
  widget_class->map = gtk_notebook_map;
  widget_class->unmap = gtk_notebook_unmap;
  widget_class->realize = gtk_notebook_realize;
637
  widget_class->unrealize = gtk_notebook_unrealize;
638 639
  widget_class->get_preferred_width = gtk_notebook_get_preferred_width;
  widget_class->get_preferred_height = gtk_notebook_get_preferred_height;
Elliot Lee's avatar
Elliot Lee committed
640
  widget_class->size_allocate = gtk_notebook_size_allocate;
641
  widget_class->draw = gtk_notebook_draw;
Elliot Lee's avatar
Elliot Lee committed
642
  widget_class->button_press_event = gtk_notebook_button_press;
643
  widget_class->button_release_event = gtk_notebook_button_release;
644
  widget_class->popup_menu = gtk_notebook_popup_menu;
645 646
  widget_class->leave_notify_event = gtk_notebook_leave_notify;
  widget_class->motion_notify_event = gtk_notebook_motion_notify;
Matthias Clasen's avatar
Matthias Clasen committed
647
  widget_class->grab_notify = gtk_notebook_grab_notify;
648
  widget_class->state_flags_changed = gtk_notebook_state_flags_changed;
649
  widget_class->focus_in_event = gtk_notebook_focus_in;
650
  widget_class->focus_out_event = gtk_notebook_focus_out;
651
  widget_class->focus = gtk_notebook_focus;
652
  widget_class->style_updated = gtk_notebook_style_updated;
653
  widget_class->drag_begin = gtk_notebook_drag_begin;
654
  widget_class->drag_end = gtk_notebook_drag_end;
655
  widget_class->drag_motion = gtk_notebook_drag_motion;
656
  widget_class->drag_leave = gtk_notebook_drag_leave;
657 658 659
  widget_class->drag_drop = gtk_notebook_drag_drop;
  widget_class->drag_data_get = gtk_notebook_drag_data_get;
  widget_class->drag_data_received = gtk_notebook_drag_data_received;
660
  widget_class->drag_failed = gtk_notebook_drag_failed;
661
  widget_class->compute_expand = gtk_notebook_compute_expand;
662

Elliot Lee's avatar
Elliot Lee committed
663 664
  container_class->add = gtk_notebook_add;
  container_class->remove = gtk_notebook_remove;
665
  container_class->forall = gtk_notebook_forall;
666
  container_class->set_focus_child = gtk_notebook_set_focus_child;
Tim Janik's avatar
Tim Janik committed
667 668
  container_class->get_child_property = gtk_notebook_get_child_property;
  container_class->set_child_property = gtk_notebook_set_child_property;
669
  container_class->child_type = gtk_notebook_child_type;
670
  container_class->get_path_for_child = gtk_notebook_get_path_for_child;
671

672
  class->switch_page = gtk_notebook_real_switch_page;
673
  class->insert_page = gtk_notebook_real_insert_page;
674

675 676
  class->focus_tab = gtk_notebook_focus_tab;
  class->select_page = gtk_notebook_select_page;
677
  class->change_current_page = gtk_notebook_change_current_page;
678
  class->move_focus_out = gtk_notebook_move_focus_out;
679
  class->reorder_tab = gtk_notebook_reorder_tab;
680
  class->create_window = gtk_notebook_create_window;
681

682
  g_object_class_install_property (gobject_class,
683 684 685 686 687 688 689 690
                                   PROP_PAGE,
                                   g_param_spec_int ("page",
                                                     P_("Page"),
                                                     P_("The index of the current page"),
                                                     -1,
                                                     G_MAXINT,
                                                     -1,
                                                     GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
691
  g_object_class_install_property (gobject_class,
692 693 694 695 696 697 698
                                   PROP_TAB_POS,
                                   g_param_spec_enum ("tab-pos",
                                                      P_("Tab Position"),
                                                      P_("Which side of the notebook holds the tabs"),
                                                      GTK_TYPE_POSITION_TYPE,
                                                      GTK_POS_TOP,
                                                      GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
699
  g_object_class_install_property (gobject_class,
700 701 702 703 704 705
                                   PROP_SHOW_TABS,
                                   g_param_spec_boolean ("show-tabs",
                                                         P_("Show Tabs"),
                                                         P_("Whether tabs should be shown"),
                                                         TRUE,
                                                         GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
706
  g_object_class_install_property (gobject_class,
707 708 709 710 711 712
                                   PROP_SHOW_BORDER,
                                   g_param_spec_boolean ("show-border",
                                                         P_("Show Border"),
                                                         P_("Whether the border should be shown"),
                                                         TRUE,
                                                         GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
713
  g_object_class_install_property (gobject_class,
714 715 716 717 718 719
                                   PROP_SCROLLABLE,
                                   g_param_spec_boolean ("scrollable",
                                                         P_("Scrollable"),
                                                         P_("If TRUE, scroll arrows are added if there are too many tabs to fit"),
                                                         FALSE,
                                                         GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
720
  g_object_class_install_property (gobject_class,
721 722 723 724 725 726
                                   PROP_ENABLE_POPUP,
                                   g_param_spec_boolean ("enable-popup",
                                                         P_("Enable Popup"),
                                                         P_("If TRUE, pressing the right mouse button on the notebook pops up a menu that you can use to go to a page"),
                                                         FALSE,
                                                         GTK_PARAM_READWRITE));
Matthias Clasen's avatar
Matthias Clasen committed
727 728

  /**
729
   * GtkNotebook:group-name:
Matthias Clasen's avatar
Matthias Clasen committed
730
   *
731
   * Group name for tab drag and drop.
Matthias Clasen's avatar
Matthias Clasen committed
732 733
   *
   * Since: 2.24
734
   */
735
  g_object_class_install_property (gobject_class,
736 737 738 739
                                   PROP_GROUP_NAME,
                                   g_param_spec_string ("group-name",
                                                        P_("Group Name"),
                                                        P_("Group name for tab drag and drop"),
740
                                                        NULL,
741
                                                        GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
742 743

  gtk_container_class_install_child_property (container_class,
744 745 746 747 748 749
                                              CHILD_PROP_TAB_LABEL,
                                              g_param_spec_string ("tab-label",
                                                                   P_("Tab label"),
                                                                   P_("The string displayed on the child's tab label"),
                                                                   NULL,
                                                                   GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
750
  gtk_container_class_install_child_property (container_class,
751 752 753 754 755 756
                                              CHILD_PROP_MENU_LABEL,
                                              g_param_spec_string ("menu-label",
                                                                   P_("Menu label"),
                                                                   P_("The string displayed in the child's menu entry"),
                                                                   NULL,
                                                                   GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
757
  gtk_container_class_install_child_property (container_class,
758 759 760 761 762 763
                                              CHILD_PROP_POSITION,
                                              g_param_spec_int ("position",
                                                                P_("Position"),
                                                                P_("The index of the child in the parent"),
                                                                -1, G_MAXINT, 0,
                                                                GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
764
  gtk_container_class_install_child_property (container_class,
765 766 767 768 769 770
                                              CHILD_PROP_TAB_EXPAND,
                                              g_param_spec_boolean ("tab-expand",
                                                                    P_("Tab expand"),
                                                                    P_("Whether to expand the child's tab"),
                                                                    FALSE,
                                                                    GTK_PARAM_READWRITE));
Tim Janik's avatar
Tim Janik committed
771
  gtk_container_class_install_child_property (container_class,
772 773 774 775 776 777
                                              CHILD_PROP_TAB_FILL,
                                              g_param_spec_boolean ("tab-fill",
                                                                    P_("Tab fill"),
                                                                    P_("Whether the child's tab should fill the allocated area"),
                                                                    TRUE,
                                                                    GTK_PARAM_READWRITE));
778

779
  gtk_container_class_install_child_property (container_class,
780 781 782 783 784 785
                                              CHILD_PROP_REORDERABLE,
                                              g_param_spec_boolean ("reorderable",
                                                                    P_("Tab reorderable"),
                                                                    P_("Whether the tab is reorderable by user action"),
                                                                    FALSE,
                                                                    GTK_PARAM_READWRITE));
786
  gtk_container_class_install_child_property (container_class,
787 788 789 790 791 792
                                              CHILD_PROP_DETACHABLE,
                                              g_param_spec_boolean ("detachable",
                                                                    P_("Tab detachable"),
                                                                    P_("Whether the tab is detachable"),
                                                                    FALSE,
                                                                    GTK_PARAM_READWRITE));
793 794 795 796

/**
 * GtkNotebook:has-secondary-backward-stepper:
 *
797 798
 * The "has-secondary-backward-stepper" property determines whether
 * a second backward arrow button is displayed on the opposite end
799 800 801
 * of the tab area.
 *
 * Since: 2.4
802
 */
803
  gtk_widget_class_install_style_property (widget_class,
804 805 806 807 808
                                           g_param_spec_boolean ("has-secondary-backward-stepper",
                                                                 P_("Secondary backward stepper"),
                                                                 P_("Display a second backward arrow button on the opposite end of the tab area"),
                                                                 FALSE,
                                                                 GTK_PARAM_READABLE));
809

810 811 812
/**
 * GtkNotebook:has-secondary-forward-stepper:
 *
813 814
 * The "has-secondary-forward-stepper" property determines whether
 * a second forward arrow button is displayed on the opposite end
815 816 817
 * of the tab area.
 *
 * Since: 2.4
818
 */
819
  gtk_widget_class_install_style_property (widget_class,
820 821 822 823 824
                                           g_param_spec_boolean ("has-secondary-forward-stepper",
                                                                 P_("Secondary forward stepper"),
                                                                 P_("Display a second forward arrow button on the opposite end of the tab area"),
                                                                 FALSE,
                                                                 GTK_PARAM_READABLE));
825

826 827 828
/**
 * GtkNotebook:has-backward-stepper:
 *
829
 * The "has-backward-stepper" property determines whether
830 831 832
 * the standard backward arrow button is displayed.
 *
 * Since: 2.4
833
 */
834
  gtk_widget_class_install_style_property (widget_class,
835 836 837 838 839
                                           g_param_spec_boolean ("has-backward-stepper",
                                                                 P_("Backward stepper"),
                                                                 P_("Display the standard backward arrow button"),
                                                                 TRUE,
                                                                 GTK_PARAM_READABLE));
840

841 842 843
/**
 * GtkNotebook:has-forward-stepper:
 *
844
 * The "has-forward-stepper" property determines whether
845 846 847
 * the standard forward arrow button is displayed.
 *
 * Since: 2.4
848
 */
849
  gtk_widget_class_install_style_property (widget_class,
850 851 852 853 854 855
                                           g_param_spec_boolean ("has-forward-stepper",
                                                                 P_("Forward stepper"),
                                                                 P_("Display the standard forward arrow button"),
                                                                 TRUE,
                                                                 GTK_PARAM_READABLE));

856 857 858 859 860 861 862
/**
 * GtkNotebook:tab-overlap:
 *
 * The "tab-overlap" property defines size of tab overlap
 * area.
 *
 * Since: 2.10
863
 */
864
  gtk_widget_class_install_style_property (widget_class,
865 866 867 868 869 870 871
                                           g_param_spec_int ("tab-overlap",
                                                             P_("Tab overlap"),
                                                             P_("Size of tab overlap area"),
                                                             G_MININT,
                                                             G_MAXINT,
                                                             2,
                                                             GTK_PARAM_READABLE));
872 873 874 875 876 877 878

/**
 * GtkNotebook:tab-curvature:
 *
 * The "tab-curvature" property defines size of tab curvature.
 *
 * Since: 2.10
879
 */
880
  gtk_widget_class_install_style_property (widget_class,
881 882 883 884 885 886 887
                                           g_param_spec_int ("tab-curvature",
                                                             P_("Tab curvature"),
                                                             P_("Size of tab curvature"),
                                                             0,
                                                             G_MAXINT,
                                                             1,
                                                             GTK_PARAM_READABLE));
888

889 890 891
  /**
   * GtkNotebook:arrow-spacing:
   *
892
   * The "arrow-spacing" property defines the spacing between the scroll
893 894 895 896 897 898
   * arrows and the tabs.
   *
   * Since: 2.10
   */
  gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("arrow-spacing",
899 900
                                                             P_("Arrow spacing"),
                                                             P_("Scroll arrow spacing"),
901 902 903 904 905
                                                             0,
                                                             G_MAXINT,
                                                             0,
                                                             GTK_PARAM_READABLE));

906 907 908 909 910 911 912 913
  /**
   * GtkNotebook::switch-page:
   * @notebook: the object which received the signal.
   * @page: the new current page
   * @page_num: the index of the page
   *
   * Emitted when the user or a function changes the current page.
   */
914
  notebook_signals[SWITCH_PAGE] =
915
    g_signal_new (I_("switch-page"),
916 917 918 919 920 921 922 923 924
                  G_TYPE_FROM_CLASS (gobject_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkNotebookClass, switch_page),
                  NULL, NULL,
                  _gtk_marshal_VOID__OBJECT_UINT,
                  G_TYPE_NONE, 2,
                  GTK_TYPE_WIDGET,
                  G_TYPE_UINT);
  notebook_signals[FOCUS_TAB] =
925
    g_signal_new (I_("focus-tab"),
Manish Singh's avatar
Manish Singh committed
926
                  G_TYPE_FROM_CLASS (gobject_class),
927 928 929
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
                  NULL, NULL,
930
                  _gtk_marshal_BOOLEAN__ENUM,
931
                  G_TYPE_BOOLEAN, 1,
932
                  GTK_TYPE_NOTEBOOK_TAB);
933
  notebook_signals[SELECT_PAGE] =
934
    g_signal_new (I_("select-page"),
Manish Singh's avatar
Manish Singh committed
935
                  G_TYPE_FROM_CLASS (gobject_class),
936 937 938
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkNotebookClass, select_page),
                  NULL, NULL,
939 940
                  _gtk_marshal_BOOLEAN__BOOLEAN,
                  G_TYPE_BOOLEAN, 1,
941
                  G_TYPE_BOOLEAN);
942
  notebook_signals[CHANGE_CURRENT_PAGE] =
943
    g_signal_new (I_("change-current-page"),
Manish Singh's avatar
Manish Singh committed
944
                  G_TYPE_FROM_CLASS (gobject_class),
945 946 947
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
                  NULL, NULL,
948 949
                  _gtk_marshal_BOOLEAN__INT,
                  G_TYPE_BOOLEAN, 1,
950
                  G_TYPE_INT);
951
  notebook_signals[MOVE_FOCUS_OUT] =
952
    g_signal_new (I_("move-focus-out"),
Manish Singh's avatar
Manish Singh committed
953
                  G_TYPE_FROM_CLASS (gobject_class),
954 955 956 957 958 959
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkNotebookClass, move_focus_out),
                  NULL, NULL,
                  _gtk_marshal_VOID__ENUM,
                  G_TYPE_NONE, 1,
                  GTK_TYPE_DIRECTION_TYPE);
960
  notebook_signals[REORDER_TAB] =
961
    g_signal_new (I_("reorder-tab"),
962 963 964 965
                  G_TYPE_FROM_CLASS (gobject_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkNotebookClass, reorder_tab),
                  NULL, NULL,
966 967
                  _gtk_marshal_BOOLEAN__ENUM_BOOLEAN,
                  G_TYPE_BOOLEAN, 2,
968
                  GTK_TYPE_DIRECTION_TYPE,
969
                  G_TYPE_BOOLEAN);
970
  /**
971
   * GtkNotebook::page-reordered:
972 973 974 975
   * @notebook: the #GtkNotebook
   * @child: the child #GtkWidget affected
   * @page_num: the new page number for @child
   *
976 977
   * the ::page-reordered signal is emitted in the notebook
   * right after a page has been reordered.
978 979
   *
   * Since: 2.10
980
   */
981
  notebook_signals[PAGE_REORDERED] =
982
    g_signal_new (I_("page-reordered"),
983
                  G_TYPE_FROM_CLASS (gobject_class),
984
                  G_SIGNAL_RUN_LAST,
985 986 987
                  G_STRUCT_OFFSET (GtkNotebookClass, page_reordered),
                  NULL, NULL,
                  _gtk_marshal_VOID__OBJECT_UINT,
988
                  G_TYPE_NONE, 2,
989 990
                  GTK_TYPE_WIDGET,
                  G_TYPE_UINT);
991
  /**
992
   * GtkNotebook::page-removed:
993 994 995 996
   * @notebook: the #GtkNotebook
   * @child: the child #GtkWidget affected
   * @page_num: the @child page number
   *
997
   * the ::page-removed signal is emitted in the notebook
998
   * right after a page is removed from the notebook.
999 1000
   *
   * Since: 2.10
1001
   */
1002
  notebook_signals[PAGE_REMOVED] =
1003
    g_signal_new (I_("page-removed"),
1004
                  G_TYPE_FROM_CLASS (gobject_class),
1005
                  G_SIGNAL_RUN_LAST,
1006 1007 1008
                  G_STRUCT_OFFSET (GtkNotebookClass, page_removed),
                  NULL, NULL,
                  _gtk_marshal_VOID__OBJECT_UINT,
1009
                  G_TYPE_NONE, 2,
1010 1011
                  GTK_TYPE_WIDGET,
                  G_TYPE_UINT);
1012
  /**
1013
   * GtkNotebook::page-added:
1014 1015 1016 1017
   * @notebook: the #GtkNotebook
   * @child: the child #GtkWidget affected
   * @page_num: the new page number for @child
   *
1018 1019
   * the ::page-added signal is emitted in the notebook
   * right after a page is added to the notebook.
1020 1021
   *
   * Since: 2.10
1022
   */
1023
  notebook_signals[PAGE_ADDED] =
1024
    g_signal_new (I_("page-added"),
1025
                  G_TYPE_FROM_CLASS (gobject_class),
1026
                  G_SIGNAL_RUN_LAST,
1027 1028 1029
                  G_STRUCT_OFFSET (GtkNotebookClass, page_added),
                  NULL, NULL,
                  _gtk_marshal_VOID__OBJECT_UINT,
1030
                  G_TYPE_NONE, 2,
1031 1032
                  GTK_TYPE_WIDGET,
                  G_TYPE_UINT);
1033

1034 1035 1036 1037 1038 1039 1040 1041
  /**
   * GtkNotebook::create-window:
   * @notebook: the #GtkNotebook emitting the signal
   * @page: the tab of @notebook that is being detached
   * @x: the X coordinate where the drop happens
   * @y: the Y coordinate where the drop happens
   *
   * The ::create-window signal is emitted when a detachable
1042
   * tab is dropped on the root window.
1043
   *
1044 1045 1046 1047
   * A handler for this signal can create a window containing
   * a notebook where the tab will be attached. It is also
   * responsible for moving/resizing the window and adding the
   * necessary properties to the notebook (e.g. the
1048
   * #GtkNotebook:group ).
1049
   *
1050 1051
   * Returns: (transfer none): a #GtkNotebook that @page should be
   *     added to, or %NULL.
1052 1053 1054
   *
   * Since: 2.12
   */
1055
  notebook_signals[CREATE_WINDOW] =
1056
    g_signal_new (I_("create-window"),
1057 1058 1059 1060 1061 1062 1063
                  G_TYPE_FROM_CLASS (gobject_class),
                  G_SIGNAL_RUN_LAST,
                  G_STRUCT_OFFSET (GtkNotebookClass, create_window),
                  gtk_object_handled_accumulator, NULL,
                  _gtk_marshal_OBJECT__OBJECT_INT_INT,
                  GTK_TYPE_NOTEBOOK, 3,
                  GTK_TYPE_WIDGET, G_TYPE_INT, G_TYPE_INT);
1064

Manish Singh's avatar
Manish Singh committed
1065
  binding_set = gtk_binding_set_by_class (class);
1066
  gtk_binding_entry_add_signal (binding_set,
1067
                                GDK_KEY_space, 0,
1068
                                "select-page", 1,
1069
                                G_TYPE_BOOLEAN, FALSE);
1070
  gtk_binding_entry_add_signal (binding_set,
1071
                                GDK_KEY_KP_Space, 0,
1072
                                "select-page", 1,
1073
                                G_TYPE_BOOLEAN, FALSE);
1074

1075
  gtk_binding_entry_add_signal (binding_set,
1076
                                GDK_KEY_Home, 0,
1077
                                "focus-tab", 1,
1078 1079
                                GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
  gtk_binding_entry_add_signal (binding_set,
1080
                                GDK_KEY_KP_Home, 0,
1081
                                "focus-tab", 1,
1082 1083
                                GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_FIRST);
  gtk_binding_entry_add_signal (binding_set,
1084
                                GDK_KEY_End, 0,
1085
                                "focus-tab", 1,
1086 1087
                                GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
  gtk_binding_entry_add_signal (binding_set,
1088
                                GDK_KEY_KP_End, 0,
1089
                                "focus-tab", 1,
1090
                                GTK_TYPE_NOTEBOOK_TAB, GTK_NOTEBOOK_TAB_LAST);
1091 1092

  gtk_binding_entry_add_signal (binding_set,
1093
                                GDK_KEY_Page_Up, GDK_CONTROL_MASK,
1094
                                "change-current-page", 1,
1095 1096
                                G_TYPE_INT, -1);
  gtk_binding_entry_add_signal (binding_set,
1097
                                GDK_KEY_Page_Down, GDK_CONTROL_MASK,
1098
                                "change-current-page", 1,
1099
                                G_TYPE_INT, 1);
1100

1101
  gtk_binding_entry_add_signal (binding_set,
1102
                                GDK_KEY_Page_Up, GDK_CONTROL_MASK | GDK_MOD1_MASK,
1103
                                "change-current-page", 1,
1104 1105
                                G_TYPE_INT, -1);
  gtk_binding_entry_add_signal (binding_set,
1106
                                GDK_KEY_Page_Down, GDK_CONTROL_MASK | GDK_MOD1_MASK,
1107
                                "change-current-page", 1,
1108 1109
                                G_TYPE_INT, 1);

1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122
  add_arrow_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP);
  add_arrow_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN);
  add_arrow_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT);
  add_arrow_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT);

  add_reorder_bindings (binding_set, GDK_KEY_Up, GTK_DIR_UP, FALSE);
  add_reorder_bindings (binding_set, GDK_KEY_Down, GTK_DIR_DOWN, FALSE);
  add_reorder_bindings (binding_set, GDK_KEY_Left, GTK_DIR_LEFT, FALSE);
  add_reorder_bindings (binding_set, GDK_KEY_Right, GTK_DIR_RIGHT, FALSE);
  add_reorder_bindings (binding_set, GDK_KEY_Home, GTK_DIR_LEFT, TRUE);
  add_reorder_bindings (binding_set, GDK_KEY_Home, GTK_DIR_UP, TRUE);
  add_reorder_bindings (binding_set, GDK_KEY_End, GTK_DIR_RIGHT, TRUE);
  add_reorder_bindings (binding_set, GDK_KEY_End, GTK_DIR_DOWN, TRUE);
1123

1124 1125
  add_tab_bindings (binding_set, GDK_CONTROL_MASK, GTK_DIR_TAB_FORWARD);
  add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
1126

1127
  g_type_class_add_private (class, sizeof (GtkNotebookPrivate));
Elliot Lee's avatar
Elliot Lee committed
1128 1129
}

1130
static void
1131 1132
gtk_notebook_init (GtkNotebook *notebook)
{
1133
  GtkNotebookPrivate *priv;
1134
  GtkStyleContext *context;
1135

1136
  gtk_widget_set_can_focus (GTK_WIDGET (notebook), TRUE);
1137
  gtk_widget_set_has_window (GTK_WIDGET (notebook), FALSE);
1138

1139 1140
  notebook->priv = G_TYPE_INSTANCE_GET_PRIVATE (notebook,
                                                GTK_TYPE_NOTEBOOK,
1141
                                                GtkNotebookPrivate);
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
  priv = notebook->priv;

  priv->cur_page = NULL;
  priv->children = NULL;
  priv->first_tab = NULL;
  priv->focus_tab = NULL;
  priv->event_window = NULL;
  priv->menu = NULL;

  priv->tab_hborder = 2;
  priv->tab_vborder = 2;

  priv->show_tabs = TRUE;
  priv->show_border = TRUE;
  priv->tab_pos = GTK_POS_TOP;
  priv->scrollable = FALSE;
  priv->in_child = 0;
  priv->click_child = 0;
  priv->button = 0;
  priv->need_timer = 0;
  priv->child_has_focus = FALSE;
  priv->have_visible_child = FALSE;
  priv->focus_out = FALSE;

  priv->has_before_previous = 1;
  priv->has_before_next     = 0;
  priv->has_after_previous  = 0;
  priv->has_after_next      = 1;
1170

1171
  priv->group = 0;
1172 1173
  priv->pressed_button = -1;
  priv->dnd_timer = 0;
1174
  priv->switch_tab_timer = 0;
1175
  priv->source_targets = gtk_target_list_new (notebook_targets,
1176
                                              G_N_ELEMENTS (notebook_targets));
1177 1178 1179 1180
  priv->operation = DRAG_OPERATION_NONE;
  priv->detached_tab = NULL;
  priv->during_detach = FALSE;
  priv->has_scrolled = FALSE;
1181

1182
  gtk_drag_dest_set (GTK_WIDGET (notebook), 0,
1183
                     notebook_targets, G_N_ELEMENTS (notebook_targets),
1184
                     GDK_ACTION_MOVE);
1185 1186

  gtk_drag_dest_set_track_motion (GTK_WIDGET (notebook), TRUE);
1187 1188 1189

  context = gtk_widget_get_style_context (GTK_WIDGET (notebook));
  gtk_style_context_add_class (context, GTK_STYLE_CLASS_NOTEBOOK);
1190 1191
}

1192 1193 1194
static void
gtk_notebook_buildable_init (GtkBuildableIface *iface)
{
1195
  iface->add_child = gtk_notebook_buildable_add_child;
1196 1197 1198
}

static void
1199
gtk_notebook_buildable_add_child (GtkBuildable  *buildable,
Matthias Clasen's avatar