gtknotebook.c 255 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>
Johan Dahlin's avatar
Johan Dahlin committed
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"
Johan Dahlin's avatar
Johan Dahlin committed
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);
Benjamin Otte's avatar
Benjamin Otte committed
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

Johan Dahlin's avatar
Johan Dahlin committed
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

Johan Dahlin's avatar
Johan Dahlin committed
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;
Benjamin Otte's avatar
Benjamin Otte committed
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;
Lars Hamann's avatar
Lars Hamann committed
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 914 915 916 917 918 919 920 921 922
  /**
   * GtkNotebook:initial-gap:
   *
   * The "initial-gap" property defines the minimum size for the initial
   * gap between the first tab.
   *
   * Since: 3.2
   */
  gtk_widget_class_install_style_property (widget_class,
                                           g_param_spec_int ("initial-gap",
                                                             P_("Initial gap"),
                                                             P_("Initial gap before the first tab"),
                                                             0,
                                                             G_MAXINT,
                                                             0,
                                                             GTK_PARAM_READABLE));

923 924 925 926 927 928 929 930
  /**
   * 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.
   */
931
  notebook_signals[SWITCH_PAGE] =
932
    g_signal_new (I_("switch-page"),
933 934 935 936 937 938 939 940 941
                  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] =
942
    g_signal_new (I_("focus-tab"),
Manish Singh's avatar
Manish Singh committed
943
                  G_TYPE_FROM_CLASS (gobject_class),
944 945 946
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkNotebookClass, focus_tab),
                  NULL, NULL,
947
                  _gtk_marshal_BOOLEAN__ENUM,
948
                  G_TYPE_BOOLEAN, 1,
949
                  GTK_TYPE_NOTEBOOK_TAB);
950
  notebook_signals[SELECT_PAGE] =
951
    g_signal_new (I_("select-page"),
Manish Singh's avatar
Manish Singh committed
952
                  G_TYPE_FROM_CLASS (gobject_class),
953 954 955
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkNotebookClass, select_page),
                  NULL, NULL,
956 957
                  _gtk_marshal_BOOLEAN__BOOLEAN,
                  G_TYPE_BOOLEAN, 1,
958
                  G_TYPE_BOOLEAN);
959
  notebook_signals[CHANGE_CURRENT_PAGE] =
960
    g_signal_new (I_("change-current-page"),
Manish Singh's avatar
Manish Singh committed
961
                  G_TYPE_FROM_CLASS (gobject_class),
962 963 964
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
                  NULL, NULL,
965 966
                  _gtk_marshal_BOOLEAN__INT,
                  G_TYPE_BOOLEAN, 1,
967
                  G_TYPE_INT);
968
  notebook_signals[MOVE_FOCUS_OUT] =
969
    g_signal_new (I_("move-focus-out"),
Manish Singh's avatar
Manish Singh committed
970
                  G_TYPE_FROM_CLASS (gobject_class),
971 972 973 974 975 976
                  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);
977
  notebook_signals[REORDER_TAB] =
978
    g_signal_new (I_("reorder-tab"),
979 980 981 982
                  G_TYPE_FROM_CLASS (gobject_class),
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                  G_STRUCT_OFFSET (GtkNotebookClass, reorder_tab),
                  NULL, NULL,
983 984
                  _gtk_marshal_BOOLEAN__ENUM_BOOLEAN,
                  G_TYPE_BOOLEAN, 2,
985
                  GTK_TYPE_DIRECTION_TYPE,
986
                  G_TYPE_BOOLEAN);
987
  /**
988
   * GtkNotebook::page-reordered:
989 990 991 992
   * @notebook: the #GtkNotebook
   * @child: the child #GtkWidget affected
   * @page_num: the new page number for @child
   *
993 994
   * the ::page-reordered signal is emitted in the notebook
   * right after a page has been reordered.
995 996
   *
   * Since: 2.10
997
   */
998
  notebook_signals[PAGE_REORDERED] =
999
    g_signal_new (I_("page-reordered"),
1000
                  G_TYPE_FROM_CLASS (gobject_class),
1001
                  G_SIGNAL_RUN_LAST,
1002 1003 1004
                  G_STRUCT_OFFSET (GtkNotebookClass, page_reordered),
                  NULL, NULL,
                  _gtk_marshal_VOID__OBJECT_UINT,
1005
                  G_TYPE_NONE, 2,
1006 1007
                  GTK_TYPE_WIDGET,
                  G_TYPE_UINT);
1008
  /**
1009
   * GtkNotebook::page-removed:
1010 1011 1012 1013
   * @notebook: the #GtkNotebook
   * @child: the child #GtkWidget affected
   * @page_num: the @child page number
   *
1014
   * the ::page-removed signal is emitted in the notebook
1015
   * right after a page is removed from the notebook.
1016 1017
   *
   * Since: 2.10
1018
   */
1019
  notebook_signals[PAGE_REMOVED] =
1020
    g_signal_new (I_("page-removed"),
1021
                  G_TYPE_FROM_CLASS (gobject_class),
1022
                  G_SIGNAL_RUN_LAST,
1023 1024 1025
                  G_STRUCT_OFFSET (GtkNotebookClass, page_removed),
                  NULL, NULL,
                  _gtk_marshal_VOID__OBJECT_UINT,
1026
                  G_TYPE_NONE, 2,
1027 1028
                  GTK_TYPE_WIDGET,
                  G_TYPE_UINT);
1029
  /**
1030
   * GtkNotebook::page-added:
1031 1032 1033 1034
   * @notebook: the #GtkNotebook
   * @child: the child #GtkWidget affected
   * @page_num: the new page number for @child
   *
1035 1036
   * the ::page-added signal is emitted in the notebook
   * right after a page is added to the notebook.
1037 1038
   *
   * Since: 2.10
1039
   */
1040
  notebook_signals[PAGE_ADDED] =
1041
    g_signal_new (I_("page-added"),
1042
                  G_TYPE_FROM_CLASS (gobject_class),
1043
                  G_SIGNAL_RUN_LAST,
1044 1045 1046
                  G_STRUCT_OFFSET (GtkNotebookClass, page_added),
                  NULL, NULL,
                  _gtk_marshal_VOID__OBJECT_UINT,
1047
                  G_TYPE_NONE, 2,
1048 1049
                  GTK_TYPE_WIDGET,
                  G_TYPE_UINT);
1050

1051 1052 1053 1054 1055 1056 1057 1058
  /**
   * 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
1059
   * tab is dropped on the root window.
1060
   *
1061 1062 1063 1064
   * 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</