forked from AuroraMiddleware/gtk
Merge branch 'popovers'
This commit is contained in:
commit
ce32476f32
@ -41,6 +41,7 @@ demos = \
|
||||
panes.c \
|
||||
pickers.c \
|
||||
pixbufs.c \
|
||||
popover.c \
|
||||
printing.c \
|
||||
revealer.c \
|
||||
rotated_text.c \
|
||||
|
@ -110,6 +110,7 @@
|
||||
<file>panes.c</file>
|
||||
<file>pickers.c</file>
|
||||
<file>pixbufs.c</file>
|
||||
<file>popover.c</file>
|
||||
<file>printing.c</file>
|
||||
<file>revealer.c</file>
|
||||
<file>rotated_text.c</file>
|
||||
@ -133,4 +134,7 @@
|
||||
<file>messages.txt</file>
|
||||
<file>apple-red.png</file>
|
||||
</gresource>
|
||||
<gresource prefix="/popover">
|
||||
<file>popover.ui</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
185
demos/gtk-demo/popover.c
Normal file
185
demos/gtk-demo/popover.c
Normal file
@ -0,0 +1,185 @@
|
||||
/* Popovers
|
||||
*
|
||||
* A bubble-like window containing contextual information or options.
|
||||
* GtkPopovers can be attached to any widget, and will be displayed
|
||||
* within the same window, but on top of all its content.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static void
|
||||
toggle_changed_cb (GtkToggleButton *button,
|
||||
GtkWidget *popover)
|
||||
{
|
||||
gtk_widget_set_visible (popover,
|
||||
gtk_toggle_button_get_active (button));
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_popover (GtkWidget *parent,
|
||||
GtkWidget *child,
|
||||
GtkPositionType pos)
|
||||
{
|
||||
GtkWidget *popover;
|
||||
|
||||
popover = gtk_popover_new (parent);
|
||||
gtk_popover_set_position (GTK_POPOVER (popover), pos);
|
||||
gtk_container_add (GTK_CONTAINER (popover), child);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (popover), 6);
|
||||
gtk_widget_show (child);
|
||||
|
||||
return popover;
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
create_complex_popover (GtkWidget *parent,
|
||||
GtkPositionType pos)
|
||||
{
|
||||
GtkWidget *popover, *window, *content;
|
||||
GtkBuilder *builder;
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
gtk_builder_add_from_resource (builder, "/popover/popover.ui", NULL);
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
content = gtk_bin_get_child (GTK_BIN (window));
|
||||
g_object_ref (content);
|
||||
gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (content)),
|
||||
content);
|
||||
gtk_widget_destroy (window);
|
||||
g_object_unref (builder);
|
||||
|
||||
popover = create_popover (parent, content, GTK_POS_BOTTOM);
|
||||
g_object_unref (content);
|
||||
|
||||
gtk_widget_set_size_request (popover, 200, -1);
|
||||
gtk_widget_set_vexpand (popover, TRUE);
|
||||
|
||||
gtk_widget_set_margin_start (popover, 10);
|
||||
gtk_widget_set_margin_end (popover, 10);
|
||||
gtk_widget_set_margin_bottom (popover, 10);
|
||||
|
||||
return popover;
|
||||
}
|
||||
|
||||
static void
|
||||
entry_size_allocate_cb (GtkEntry *entry,
|
||||
GtkAllocation *allocation,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkEntryIconPosition popover_pos;
|
||||
GtkPopover *popover = user_data;
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
if (gtk_widget_is_visible (GTK_WIDGET (popover)))
|
||||
{
|
||||
popover_pos =
|
||||
GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (entry),
|
||||
"popover-icon-pos"));
|
||||
gtk_entry_get_icon_area (entry, popover_pos, &rect);
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (popover), &rect);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
entry_icon_press_cb (GtkEntry *entry,
|
||||
GtkEntryIconPosition icon_pos,
|
||||
GdkEvent *event,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkWidget *popover = user_data;
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
gtk_entry_get_icon_area (entry, icon_pos, &rect);
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (popover), &rect);
|
||||
gtk_widget_show (popover);
|
||||
|
||||
g_object_set_data (G_OBJECT (entry), "popover-icon-pos",
|
||||
GUINT_TO_POINTER (icon_pos));
|
||||
}
|
||||
|
||||
static void
|
||||
day_selected_cb (GtkCalendar *calendar,
|
||||
gpointer user_data)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
GtkAllocation allocation;
|
||||
GtkWidget *popover;
|
||||
GdkEvent *event;
|
||||
|
||||
event = gtk_get_current_event ();
|
||||
|
||||
if (event->type != GDK_BUTTON_PRESS)
|
||||
return;
|
||||
|
||||
gdk_window_coords_to_parent (event->button.window,
|
||||
event->button.x, event->button.y,
|
||||
&event->button.x, &event->button.y);
|
||||
gtk_widget_get_allocation (GTK_WIDGET (calendar), &allocation);
|
||||
rect.x = event->button.x - allocation.x;
|
||||
rect.y = event->button.y - allocation.y;
|
||||
rect.width = rect.height = 1;
|
||||
|
||||
popover = create_popover (GTK_WIDGET (calendar),
|
||||
gtk_entry_new (),
|
||||
GTK_POS_BOTTOM);
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (popover), &rect);
|
||||
|
||||
gtk_widget_show (popover);
|
||||
|
||||
gdk_event_free (event);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
do_popover (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
GtkWidget *popover, *box, *widget;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 24);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (box), 24);
|
||||
gtk_container_add (GTK_CONTAINER (window), box);
|
||||
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &window);
|
||||
|
||||
widget = gtk_toggle_button_new_with_label ("Button");
|
||||
popover = create_popover (widget,
|
||||
gtk_label_new ("This popover does not grab input"),
|
||||
GTK_POS_TOP);
|
||||
gtk_popover_set_modal (GTK_POPOVER (popover), FALSE);
|
||||
g_signal_connect (widget, "toggled",
|
||||
G_CALLBACK (toggle_changed_cb), popover);
|
||||
gtk_container_add (GTK_CONTAINER (box), widget);
|
||||
|
||||
widget = gtk_entry_new ();
|
||||
popover = create_complex_popover (widget, GTK_POS_TOP);
|
||||
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (widget),
|
||||
GTK_ENTRY_ICON_PRIMARY, "edit-find");
|
||||
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (widget),
|
||||
GTK_ENTRY_ICON_SECONDARY, "edit-clear");
|
||||
|
||||
g_signal_connect (widget, "icon-press",
|
||||
G_CALLBACK (entry_icon_press_cb), popover);
|
||||
g_signal_connect (widget, "size-allocate",
|
||||
G_CALLBACK (entry_size_allocate_cb), popover);
|
||||
gtk_container_add (GTK_CONTAINER (box), widget);
|
||||
|
||||
widget = gtk_calendar_new ();
|
||||
g_signal_connect (widget, "day-selected",
|
||||
G_CALLBACK (day_selected_cb), NULL);
|
||||
gtk_container_add (GTK_CONTAINER (box), widget);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_widget_show_all (window);
|
||||
else
|
||||
{
|
||||
gtk_widget_destroy (window);
|
||||
window = NULL;
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
103
demos/gtk-demo/popover.ui
Normal file
103
demos/gtk-demo/popover.ui
Normal file
@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.16.0 on Wed Nov 13 16:45:55 2013 -->
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 3.10 -->
|
||||
<object class="GtkListStore" id="liststore1">
|
||||
<columns>
|
||||
<!-- column-name Name -->
|
||||
<column type="gchararray"/>
|
||||
</columns>
|
||||
<data>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Item 1</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Item 2</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Item 3</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Item 4</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Item 5</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Item 6</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Item 7</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Item 8</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Item 9</col>
|
||||
</row>
|
||||
<row>
|
||||
<col id="0" translatable="yes">Item 10</col>
|
||||
</row>
|
||||
</data>
|
||||
</object>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="can_focus">False</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="box">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="primary_icon_name">edit-find</property>
|
||||
<property name="secondary_icon_name">edit-clear</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="shadow_type">in</property>
|
||||
<child>
|
||||
<object class="GtkTreeView" id="treeview1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="model">liststore1</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<property name="enable_search">False</property>
|
||||
<property name="search_column">2</property>
|
||||
<child internal-child="selection">
|
||||
<object class="GtkTreeSelection" id="treeview-selection1"/>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkTreeViewColumn" id="column1">
|
||||
<child>
|
||||
<object class="GtkCellRendererText" id="cellrenderer1"/>
|
||||
<attributes>
|
||||
<attribute name="text">0</attribute>
|
||||
</attributes>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
@ -190,6 +190,7 @@
|
||||
<xi:include href="xml/gtkmenutoolbutton.xml" />
|
||||
<xi:include href="xml/gtktoggletoolbutton.xml" />
|
||||
<xi:include href="xml/gtkradiotoolbutton.xml" />
|
||||
<xi:include href="xml/gtkpopover.xml" />
|
||||
</chapter>
|
||||
|
||||
<chapter id="SelectorWidgets">
|
||||
|
@ -7853,3 +7853,18 @@ gtk_flow_box_child_get_index
|
||||
gtk_flow_box_child_is_selected
|
||||
gtk_flow_box_child_changed
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkpopover</FILE>
|
||||
<TITLE>GtkPopover</TITLE>
|
||||
GtkPopover
|
||||
gtk_popover_new
|
||||
gtk_popover_set_relative_to
|
||||
gtk_popover_get_relative_to
|
||||
gtk_popover_set_pointing_to
|
||||
gtk_popover_get_pointing_to
|
||||
gtk_popover_set_position
|
||||
gtk_popover_get_position
|
||||
gtk_popover_set_modal
|
||||
gtk_popover_get_modal
|
||||
</SECTION>
|
||||
|
@ -126,6 +126,7 @@ gtk_paned_get_type
|
||||
gtk_paper_size_get_type
|
||||
gtk_places_sidebar_get_type
|
||||
@ENABLE_ON_X11@gtk_plug_get_type
|
||||
gtk_popover_get_type
|
||||
@DISABLE_ON_W32@gtk_printer_get_type
|
||||
gtk_print_context_get_type
|
||||
@DISABLE_ON_W32@gtk_print_job_get_type
|
||||
|
@ -296,6 +296,7 @@ gtk_public_h_sources = \
|
||||
gtkpapersize.h \
|
||||
gtkplacessidebar.h \
|
||||
gtkplug.h \
|
||||
gtkpopover.h \
|
||||
gtkprintcontext.h \
|
||||
gtkprintoperation.h \
|
||||
gtkprintoperationpreview.h \
|
||||
@ -411,7 +412,6 @@ gtk_private_h_sources = \
|
||||
gtkbookmarksmanager.h \
|
||||
gtkborderimageprivate.h \
|
||||
gtkboxprivate.h \
|
||||
gtkbubblewindowprivate.h \
|
||||
gtkbuilderprivate.h \
|
||||
gtkbuttonprivate.h \
|
||||
gtkcairoblurprivate.h \
|
||||
@ -490,6 +490,7 @@ gtk_private_h_sources = \
|
||||
gtkkeyhash.h \
|
||||
gtklabelprivate.h \
|
||||
gtklockbuttonprivate.h \
|
||||
gtkmagnifierprivate.h \
|
||||
gtkmenubuttonprivate.h \
|
||||
gtkmenuprivate.h \
|
||||
gtkmenuitemprivate.h \
|
||||
@ -629,7 +630,6 @@ gtk_base_c_sources = \
|
||||
gtkborder.c \
|
||||
gtkborderimage.c \
|
||||
gtkbox.c \
|
||||
gtkbubblewindow.c \
|
||||
gtkbuildable.c \
|
||||
gtkbuilder.c \
|
||||
gtkbuilderparser.c \
|
||||
@ -764,6 +764,7 @@ gtk_base_c_sources = \
|
||||
gtkliststore.c \
|
||||
gtklockbutton.c \
|
||||
gtkmain.c \
|
||||
gtkmagnifier.c \
|
||||
gtkmarshalers.c \
|
||||
gtkmenu.c \
|
||||
gtkmenubar.c \
|
||||
@ -801,6 +802,7 @@ gtk_base_c_sources = \
|
||||
gtkprivatetypebuiltins.c \
|
||||
gtkprogressbar.c \
|
||||
gtkpixelcache.c \
|
||||
gtkpopover.c \
|
||||
gtkradiobutton.c \
|
||||
gtkradiomenuitem.c \
|
||||
gtkradiotoolbutton.c \
|
||||
|
@ -144,6 +144,7 @@
|
||||
#include <gtk/gtkpapersize.h>
|
||||
#include <gtk/gtkpaned.h>
|
||||
#include <gtk/gtkplacessidebar.h>
|
||||
#include <gtk/gtkpopover.h>
|
||||
#include <gtk/gtkprintcontext.h>
|
||||
#include <gtk/gtkprintoperation.h>
|
||||
#include <gtk/gtkprintoperationpreview.h>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,81 +0,0 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright © 2013 Carlos Garnacho <carlosg@gnome.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_BUBBLE_WINDOW_H__
|
||||
#define __GTK_BUBBLE_WINDOW_H__
|
||||
|
||||
#include <gtk/gtkwindow.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_BUBBLE_WINDOW (_gtk_bubble_window_get_type ())
|
||||
#define GTK_BUBBLE_WINDOW(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_BUBBLE_WINDOW, GtkBubbleWindow))
|
||||
#define GTK_BUBBLE_WINDOW_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GTK_TYPE_BUBBLE_WINDOW, GtkBubbleWindowClass))
|
||||
#define GTK_IS_BUBBLE_WINDOW(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_BUBBLE_WINDOW))
|
||||
#define GTK_IS_BUBBLE_WINDOW_CLASS(o) (G_TYPE_CHECK_CLASS_TYPE ((o), GTK_TYPE_BUBBLE_WINDOW))
|
||||
#define GTK_BUBBLE_WINDOW_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_BUBBLE_WINDOW, GtkBubbleWindowClass))
|
||||
|
||||
typedef struct _GtkBubbleWindow GtkBubbleWindow;
|
||||
typedef struct _GtkBubbleWindowClass GtkBubbleWindowClass;
|
||||
|
||||
struct _GtkBubbleWindow
|
||||
{
|
||||
GtkWindow parent_instance;
|
||||
|
||||
/*< private >*/
|
||||
gpointer priv;
|
||||
};
|
||||
|
||||
struct _GtkBubbleWindowClass
|
||||
{
|
||||
GtkWindowClass parent_class;
|
||||
};
|
||||
|
||||
GType _gtk_bubble_window_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * _gtk_bubble_window_new (void);
|
||||
|
||||
void _gtk_bubble_window_set_relative_to (GtkBubbleWindow *window,
|
||||
GdkWindow *relative_to);
|
||||
GdkWindow * _gtk_bubble_window_get_relative_to (GtkBubbleWindow *window);
|
||||
|
||||
void _gtk_bubble_window_set_pointing_to (GtkBubbleWindow *window,
|
||||
cairo_rectangle_int_t *rect);
|
||||
gboolean _gtk_bubble_window_get_pointing_to (GtkBubbleWindow *window,
|
||||
cairo_rectangle_int_t *rect);
|
||||
void _gtk_bubble_window_set_position (GtkBubbleWindow *window,
|
||||
GtkPositionType position);
|
||||
|
||||
GtkPositionType
|
||||
_gtk_bubble_window_get_position (GtkBubbleWindow *window);
|
||||
|
||||
void _gtk_bubble_window_popup (GtkBubbleWindow *window,
|
||||
GdkWindow *relative_to,
|
||||
cairo_rectangle_int_t *pointing_to,
|
||||
GtkPositionType position);
|
||||
|
||||
void _gtk_bubble_window_popdown (GtkBubbleWindow *window);
|
||||
|
||||
gboolean _gtk_bubble_window_grab (GtkBubbleWindow *window,
|
||||
GdkDevice *device,
|
||||
guint32 activate_time);
|
||||
|
||||
void _gtk_bubble_window_ungrab (GtkBubbleWindow *window);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_BUBBLE_WINDOW_H__ */
|
129
gtk/gtkentry.c
129
gtk/gtkentry.c
@ -63,8 +63,9 @@
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtktexthandleprivate.h"
|
||||
#include "gtkbubblewindowprivate.h"
|
||||
#include "gtkpopover.h"
|
||||
#include "gtktoolbar.h"
|
||||
#include "gtkmagnifierprivate.h"
|
||||
|
||||
#include "a11y/gtkentryaccessible.h"
|
||||
|
||||
@ -158,11 +159,14 @@ struct _GtkEntryPrivate
|
||||
|
||||
gchar *placeholder_text;
|
||||
|
||||
GtkBubbleWindow *bubble_window;
|
||||
GtkWidget *bubble_window;
|
||||
GtkTextHandle *text_handle;
|
||||
GtkWidget *selection_bubble;
|
||||
guint selection_bubble_timeout_id;
|
||||
|
||||
GtkWidget *magnifier_popover;
|
||||
GtkWidget *magnifier;
|
||||
|
||||
gfloat xalign;
|
||||
|
||||
gint ascent; /* font ascent in pango units */
|
||||
@ -2665,6 +2669,18 @@ gtk_entry_init (GtkEntry *entry)
|
||||
G_CALLBACK (gtk_entry_handle_dragged), entry);
|
||||
g_signal_connect (priv->text_handle, "drag-finished",
|
||||
G_CALLBACK (gtk_entry_handle_drag_finished), entry);
|
||||
|
||||
priv->magnifier = _gtk_magnifier_new (GTK_WIDGET (entry));
|
||||
gtk_widget_set_size_request (priv->magnifier, 100, 60);
|
||||
_gtk_magnifier_set_magnification (GTK_MAGNIFIER (priv->magnifier), 2.0);
|
||||
priv->magnifier_popover = gtk_popover_new (GTK_WIDGET (entry));
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (priv->magnifier_popover),
|
||||
GTK_STYLE_CLASS_OSD);
|
||||
gtk_popover_set_modal (GTK_POPOVER (priv->magnifier_popover), FALSE);
|
||||
gtk_container_add (GTK_CONTAINER (priv->magnifier_popover),
|
||||
priv->magnifier);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (priv->magnifier_popover), 4);
|
||||
gtk_widget_show (priv->magnifier);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2904,6 +2920,7 @@ gtk_entry_finalize (GObject *object)
|
||||
if (priv->selection_bubble)
|
||||
gtk_widget_destroy (priv->selection_bubble);
|
||||
|
||||
gtk_widget_destroy (priv->magnifier_popover);
|
||||
g_object_unref (priv->text_handle);
|
||||
g_free (priv->placeholder_text);
|
||||
g_free (priv->im_module);
|
||||
@ -3209,7 +3226,6 @@ gtk_entry_realize (GtkWidget *widget)
|
||||
|
||||
gtk_entry_adjust_scroll (entry);
|
||||
gtk_entry_update_primary_selection (entry);
|
||||
_gtk_text_handle_set_relative_to (priv->text_handle, priv->text_area);
|
||||
|
||||
/* If the icon positions are already setup, create their windows.
|
||||
* Otherwise if they don't exist yet, then construct_icon_info()
|
||||
@ -3237,7 +3253,6 @@ gtk_entry_unrealize (GtkWidget *widget)
|
||||
gtk_entry_reset_layout (entry);
|
||||
|
||||
gtk_im_context_set_client_window (priv->im_context, NULL);
|
||||
_gtk_text_handle_set_relative_to (priv->text_handle, NULL);
|
||||
|
||||
clipboard = gtk_widget_get_clipboard (widget, GDK_SELECTION_PRIMARY);
|
||||
if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (entry))
|
||||
@ -4062,13 +4077,22 @@ gtk_entry_move_handle (GtkEntry *entry,
|
||||
}
|
||||
else
|
||||
{
|
||||
GtkAllocation primary, secondary;
|
||||
GdkRectangle rect;
|
||||
gint win_x, win_y;
|
||||
|
||||
rect.x = CLAMP (x, 0, gdk_window_get_width (priv->text_area));
|
||||
rect.y = y;
|
||||
get_icon_allocations (entry, &primary, &secondary);
|
||||
gtk_entry_get_text_area_size (entry, &win_x, &win_y, NULL, NULL);
|
||||
rect.x = CLAMP (x, 0, gdk_window_get_width (priv->text_area)) + win_x;
|
||||
rect.y = y + win_y;
|
||||
rect.width = 1;
|
||||
rect.height = height;
|
||||
|
||||
if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
|
||||
rect.x += secondary.width;
|
||||
else
|
||||
rect.x += primary.width;
|
||||
|
||||
_gtk_text_handle_set_visible (priv->text_handle, pos, TRUE);
|
||||
_gtk_text_handle_set_position (priv->text_handle, pos, &rect);
|
||||
}
|
||||
@ -4412,7 +4436,10 @@ gtk_entry_button_release (GtkWidget *widget,
|
||||
priv->in_drag = 0;
|
||||
}
|
||||
else if (is_touchscreen)
|
||||
gtk_entry_selection_bubble_popup_set (entry);
|
||||
{
|
||||
gtk_entry_selection_bubble_popup_set (entry);
|
||||
gtk_widget_hide (priv->magnifier_popover);
|
||||
}
|
||||
|
||||
priv->button = 0;
|
||||
priv->device = NULL;
|
||||
@ -4435,6 +4462,36 @@ _gtk_entry_get_selected_text (GtkEntry *entry)
|
||||
return text;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_entry_show_magnifier (GtkEntry *entry,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
GtkAllocation allocation, primary, secondary;
|
||||
cairo_rectangle_int_t rect;
|
||||
GtkEntryPrivate *priv;
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (entry), &allocation);
|
||||
get_icon_allocations (entry, &primary, &secondary);
|
||||
|
||||
priv = entry->priv;
|
||||
rect.x = CLAMP (x, 0, allocation.width - primary.width - secondary.width);
|
||||
rect.width = 1;
|
||||
rect.y = 0;
|
||||
rect.height = allocation.height;
|
||||
|
||||
if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
|
||||
rect.x += secondary.width;
|
||||
else
|
||||
rect.x += primary.width;
|
||||
|
||||
_gtk_magnifier_set_coords (GTK_MAGNIFIER (priv->magnifier), rect.x,
|
||||
rect.y + allocation.height / 2);
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (priv->magnifier_popover),
|
||||
&rect);
|
||||
gtk_widget_show (priv->magnifier_popover);
|
||||
}
|
||||
|
||||
static gint
|
||||
gtk_entry_motion_notify (GtkWidget *widget,
|
||||
GdkEventMotion *event)
|
||||
@ -4603,10 +4660,19 @@ gtk_entry_motion_notify (GtkWidget *widget,
|
||||
|
||||
/* Update touch handles' position */
|
||||
if (test_touchscreen || input_source == GDK_SOURCE_TOUCHSCREEN)
|
||||
gtk_entry_update_handles (entry,
|
||||
(priv->current_pos == priv->selection_bound) ?
|
||||
GTK_TEXT_HANDLE_MODE_CURSOR :
|
||||
GTK_TEXT_HANDLE_MODE_SELECTION);
|
||||
{
|
||||
gint x, y;
|
||||
|
||||
gtk_entry_update_handles (entry,
|
||||
(priv->current_pos == priv->selection_bound) ?
|
||||
GTK_TEXT_HANDLE_MODE_CURSOR :
|
||||
GTK_TEXT_HANDLE_MODE_SELECTION);
|
||||
|
||||
gtk_entry_get_text_area_size (entry, &x, &y, NULL, NULL);
|
||||
x += event->x;
|
||||
y += event->y;
|
||||
gtk_entry_show_magnifier (entry, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -6403,6 +6469,7 @@ gtk_entry_handle_dragged (GtkTextHandle *handle,
|
||||
{
|
||||
gint cursor_pos, selection_bound_pos, tmp_pos;
|
||||
GtkEntryPrivate *priv = entry->priv;
|
||||
GtkAllocation primary, secondary;
|
||||
GtkTextHandleMode mode;
|
||||
gint *min, *max;
|
||||
|
||||
@ -6411,6 +6478,14 @@ gtk_entry_handle_dragged (GtkTextHandle *handle,
|
||||
cursor_pos = priv->current_pos;
|
||||
selection_bound_pos = priv->selection_bound;
|
||||
mode = _gtk_text_handle_get_mode (handle);
|
||||
|
||||
get_icon_allocations (entry, &primary, &secondary);
|
||||
|
||||
if (gtk_widget_get_direction (GTK_WIDGET (entry)) == GTK_TEXT_DIR_RTL)
|
||||
x -= secondary.width;
|
||||
else
|
||||
x -= primary.width;
|
||||
|
||||
tmp_pos = gtk_entry_find_position (entry, x + priv->scroll_offset);
|
||||
|
||||
if (mode == GTK_TEXT_HANDLE_MODE_CURSOR ||
|
||||
@ -6458,6 +6533,8 @@ gtk_entry_handle_dragged (GtkTextHandle *handle,
|
||||
|
||||
gtk_entry_update_handles (entry, mode);
|
||||
}
|
||||
|
||||
gtk_entry_show_magnifier (entry, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -6466,6 +6543,7 @@ gtk_entry_handle_drag_finished (GtkTextHandle *handle,
|
||||
GtkEntry *entry)
|
||||
{
|
||||
gtk_entry_selection_bubble_popup_set (entry);
|
||||
gtk_widget_hide (entry->priv->magnifier_popover);
|
||||
}
|
||||
|
||||
|
||||
@ -9361,7 +9439,7 @@ activate_bubble_cb (GtkWidget *item,
|
||||
{
|
||||
const gchar *signal = g_object_get_data (G_OBJECT (item), "gtk-signal");
|
||||
g_signal_emit_by_name (entry, signal);
|
||||
_gtk_bubble_window_popdown (GTK_BUBBLE_WINDOW (entry->priv->selection_bubble));
|
||||
gtk_widget_hide (entry->priv->selection_bubble);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -9372,6 +9450,7 @@ append_bubble_action (GtkEntry *entry,
|
||||
gboolean sensitive)
|
||||
{
|
||||
GtkToolItem *item = gtk_tool_button_new (NULL, label);
|
||||
gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (item), TRUE);
|
||||
g_object_set_data (G_OBJECT (item), I_("gtk-signal"), (char *)signal);
|
||||
g_signal_connect (item, "clicked", G_CALLBACK (activate_bubble_cb), entry);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (item), sensitive);
|
||||
@ -9387,7 +9466,7 @@ bubble_targets_received (GtkClipboard *clipboard,
|
||||
GtkEntry *entry = user_data;
|
||||
GtkEntryPrivate *priv = entry->priv;
|
||||
cairo_rectangle_int_t rect;
|
||||
GtkAllocation allocation;
|
||||
GtkAllocation allocation, primary, secondary;
|
||||
gint start_x, end_x;
|
||||
gboolean has_selection;
|
||||
gboolean has_clipboard;
|
||||
@ -9405,7 +9484,13 @@ bubble_targets_received (GtkClipboard *clipboard,
|
||||
if (priv->selection_bubble)
|
||||
gtk_widget_destroy (priv->selection_bubble);
|
||||
|
||||
priv->selection_bubble = _gtk_bubble_window_new ();
|
||||
priv->selection_bubble = gtk_popover_new (GTK_WIDGET (entry));
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (priv->selection_bubble),
|
||||
GTK_STYLE_CLASS_OSD);
|
||||
gtk_popover_set_position (GTK_POPOVER (priv->selection_bubble),
|
||||
GTK_POS_TOP);
|
||||
gtk_popover_set_modal (GTK_POPOVER (priv->selection_bubble), FALSE);
|
||||
|
||||
toolbar = GTK_WIDGET (gtk_toolbar_new ());
|
||||
gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_TEXT);
|
||||
gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), FALSE);
|
||||
@ -9434,7 +9519,9 @@ bubble_targets_received (GtkClipboard *clipboard,
|
||||
start_x -= priv->scroll_offset;
|
||||
start_x = CLAMP (start_x, 0, gdk_window_get_width (priv->text_area));
|
||||
|
||||
rect.y = 0;
|
||||
gtk_entry_get_text_area_size (entry, &rect.x, &rect.y, NULL, NULL);
|
||||
get_icon_allocations (entry, &primary, &secondary);
|
||||
rect.x += primary.width;
|
||||
rect.height = gdk_window_get_height (priv->text_area);
|
||||
|
||||
if (has_selection)
|
||||
@ -9442,17 +9529,17 @@ bubble_targets_received (GtkClipboard *clipboard,
|
||||
end_x = gtk_entry_get_selection_bound_location (entry) - priv->scroll_offset;
|
||||
end_x = CLAMP (end_x, 0, gdk_window_get_width (priv->text_area));
|
||||
|
||||
rect.x = MIN (start_x, end_x);
|
||||
rect.width = MAX (start_x, end_x) - rect.x;
|
||||
rect.x += MIN (start_x, end_x);
|
||||
rect.width = MAX (start_x, end_x) - MIN (start_x, end_x);
|
||||
}
|
||||
else
|
||||
{
|
||||
rect.x = start_x;
|
||||
rect.x += start_x;
|
||||
rect.width = 0;
|
||||
}
|
||||
|
||||
_gtk_bubble_window_popup (GTK_BUBBLE_WINDOW (priv->selection_bubble),
|
||||
priv->text_area, &rect, GTK_POS_TOP);
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (priv->selection_bubble), &rect);
|
||||
gtk_widget_show (priv->selection_bubble);
|
||||
|
||||
priv->selection_bubble_timeout_id = 0;
|
||||
}
|
||||
@ -9477,7 +9564,7 @@ gtk_entry_selection_bubble_popup_unset (GtkEntry *entry)
|
||||
priv = entry->priv;
|
||||
|
||||
if (priv->selection_bubble)
|
||||
_gtk_bubble_window_popdown (GTK_BUBBLE_WINDOW (priv->selection_bubble));
|
||||
gtk_widget_hide (priv->selection_bubble);
|
||||
|
||||
if (priv->selection_bubble_timeout_id)
|
||||
{
|
||||
|
269
gtk/gtkmagnifier.c
Normal file
269
gtk/gtkmagnifier.c
Normal file
@ -0,0 +1,269 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright © 2013 Carlos Garnacho <carlosg@gnome.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "gtk/gtk.h"
|
||||
#include "gtkmagnifierprivate.h"
|
||||
#include "gtkintl.h"
|
||||
|
||||
enum {
|
||||
PROP_INSPECTED = 1,
|
||||
PROP_MAGNIFICATION
|
||||
};
|
||||
|
||||
typedef struct _GtkMagnifierPrivate GtkMagnifierPrivate;
|
||||
|
||||
struct _GtkMagnifierPrivate
|
||||
{
|
||||
GtkWidget *inspected;
|
||||
gdouble magnification;
|
||||
gint x;
|
||||
gint y;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkMagnifier, _gtk_magnifier,
|
||||
GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
_gtk_magnifier_set_property (GObject *object,
|
||||
guint param_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (param_id)
|
||||
{
|
||||
case PROP_INSPECTED:
|
||||
_gtk_magnifier_set_inspected (GTK_MAGNIFIER (object),
|
||||
g_value_get_object (value));
|
||||
break;
|
||||
case PROP_MAGNIFICATION:
|
||||
_gtk_magnifier_set_magnification (GTK_MAGNIFIER (object),
|
||||
g_value_get_double (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_magnifier_get_property (GObject *object,
|
||||
guint param_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkMagnifier *magnifier;
|
||||
GtkMagnifierPrivate *priv;
|
||||
|
||||
magnifier = GTK_MAGNIFIER (object);
|
||||
priv = _gtk_magnifier_get_instance_private (magnifier);
|
||||
|
||||
switch (param_id)
|
||||
{
|
||||
case PROP_INSPECTED:
|
||||
g_value_set_object (value, priv->inspected);
|
||||
break;
|
||||
case PROP_MAGNIFICATION:
|
||||
g_value_set_double (value, priv->magnification);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_gtk_magnifier_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GtkAllocation allocation, inspected_alloc;
|
||||
GtkMagnifier *magnifier;
|
||||
GtkMagnifierPrivate *priv;
|
||||
gdouble x, y;
|
||||
|
||||
magnifier = GTK_MAGNIFIER (widget);
|
||||
priv = _gtk_magnifier_get_instance_private (magnifier);
|
||||
|
||||
if (!gtk_widget_is_visible (priv->inspected))
|
||||
return FALSE;
|
||||
|
||||
gtk_widget_get_allocation (widget, &allocation);
|
||||
gtk_widget_get_allocation (priv->inspected, &inspected_alloc);
|
||||
cairo_translate (cr, allocation.width / 2, allocation.height / 2);
|
||||
|
||||
x = CLAMP (priv->x, 0, inspected_alloc.width);
|
||||
y = CLAMP (priv->y, 0, inspected_alloc.height);
|
||||
|
||||
cairo_save (cr);
|
||||
cairo_scale (cr, priv->magnification, priv->magnification);
|
||||
cairo_translate (cr, -x, -y);
|
||||
gtk_widget_draw (priv->inspected, cr);
|
||||
cairo_restore (cr);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_magnifier_class_init (GtkMagnifierClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->set_property = _gtk_magnifier_set_property;
|
||||
object_class->get_property = _gtk_magnifier_get_property;
|
||||
|
||||
widget_class->draw = _gtk_magnifier_draw;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_INSPECTED,
|
||||
g_param_spec_object (P_("inspected"),
|
||||
P_("Inspected"),
|
||||
P_("Inspected widget"),
|
||||
GTK_TYPE_WIDGET,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_MAGNIFICATION,
|
||||
g_param_spec_double (P_("magnification"),
|
||||
P_("magnification"),
|
||||
P_("magnification"),
|
||||
1, G_MAXDOUBLE, 1,
|
||||
G_PARAM_READWRITE));
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_magnifier_init (GtkMagnifier *magnifier)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET (magnifier);
|
||||
GtkMagnifierPrivate *priv;
|
||||
|
||||
priv = _gtk_magnifier_get_instance_private (magnifier);
|
||||
|
||||
gtk_widget_set_events (widget,
|
||||
gtk_widget_get_events (widget) |
|
||||
GDK_EXPOSURE_MASK);
|
||||
|
||||
gtk_widget_set_has_window (widget, FALSE);
|
||||
priv->magnification = 1;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
_gtk_magnifier_new (GtkWidget *inspected)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (inspected), NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_MAGNIFIER,
|
||||
"inspected", inspected,
|
||||
NULL);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
_gtk_magnifier_get_inspected (GtkMagnifier *magnifier)
|
||||
{
|
||||
GtkMagnifierPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_MAGNIFIER (magnifier), NULL);
|
||||
|
||||
priv = _gtk_magnifier_get_instance_private (magnifier);
|
||||
|
||||
return priv->inspected;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_magnifier_set_inspected (GtkMagnifier *magnifier,
|
||||
GtkWidget *inspected)
|
||||
{
|
||||
GtkMagnifierPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_MAGNIFIER (magnifier), NULL);
|
||||
|
||||
priv = _gtk_magnifier_get_instance_private (magnifier);
|
||||
|
||||
if (priv->inspected == inspected)
|
||||
return;
|
||||
|
||||
priv->inspected = inspected;
|
||||
g_object_notify (G_OBJECT (magnifier), "inspected");
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_magnifier_set_coords (GtkMagnifier *magnifier,
|
||||
gdouble x,
|
||||
gdouble y)
|
||||
{
|
||||
GtkMagnifierPrivate *priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_MAGNIFIER (magnifier));
|
||||
|
||||
priv = _gtk_magnifier_get_instance_private (magnifier);
|
||||
|
||||
if (priv->x == x && priv->y == y)
|
||||
return;
|
||||
|
||||
priv->x = x;
|
||||
priv->y = y;
|
||||
|
||||
if (gtk_widget_is_visible (GTK_WIDGET (magnifier)))
|
||||
gtk_widget_queue_draw (GTK_WIDGET (magnifier));
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_magnifier_get_coords (GtkMagnifier *magnifier,
|
||||
gdouble *x,
|
||||
gdouble *y)
|
||||
{
|
||||
GtkMagnifierPrivate *priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_MAGNIFIER (magnifier));
|
||||
|
||||
priv = _gtk_magnifier_get_instance_private (magnifier);
|
||||
|
||||
if (x)
|
||||
*x = priv->x;
|
||||
|
||||
if (y)
|
||||
*y = priv->y;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_magnifier_set_magnification (GtkMagnifier *magnifier,
|
||||
gdouble magnification)
|
||||
{
|
||||
GtkMagnifierPrivate *priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_MAGNIFIER (magnifier));
|
||||
|
||||
priv = _gtk_magnifier_get_instance_private (magnifier);
|
||||
|
||||
if (priv->magnification == magnification)
|
||||
return;
|
||||
|
||||
priv->magnification = magnification;
|
||||
g_object_notify (G_OBJECT (magnifier), "magnification");
|
||||
|
||||
if (gtk_widget_is_visible (GTK_WIDGET (magnifier)))
|
||||
gtk_widget_queue_draw (GTK_WIDGET (magnifier));
|
||||
}
|
||||
|
||||
gdouble
|
||||
_gtk_magnifier_get_magnification (GtkMagnifier *magnifier)
|
||||
{
|
||||
GtkMagnifierPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_MAGNIFIER (magnifier), 1);
|
||||
|
||||
priv = _gtk_magnifier_get_instance_private (magnifier);
|
||||
|
||||
return priv->magnification;
|
||||
}
|
64
gtk/gtkmagnifierprivate.h
Normal file
64
gtk/gtkmagnifierprivate.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright © 2013 Carlos Garnacho <carlosg@gnome.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_MAGNIFIER_H__
|
||||
#define __GTK_MAGNIFIER_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_MAGNIFIER (_gtk_magnifier_get_type ())
|
||||
#define GTK_MAGNIFIER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_MAGNIFIER, GtkMagnifier))
|
||||
#define GTK_MAGNIFIER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GTK_TYPE_MAGNIFIER, GtkMagnifierClass))
|
||||
#define GTK_IS_MAGNIFIER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_MAGNIFIER))
|
||||
#define GTK_IS_MAGNIFIER_CLASS(o) (G_TYPE_CHECK_CLASS_TYPE ((o), GTK_TYPE_MAGNIFIER))
|
||||
#define GTK_MAGNIFIER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_MAGNIFIER, GtkMagnifierClass))
|
||||
|
||||
typedef struct _GtkMagnifier GtkMagnifier;
|
||||
typedef struct _GtkMagnifierClass GtkMagnifierClass;
|
||||
|
||||
struct _GtkMagnifier
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
};
|
||||
|
||||
struct _GtkMagnifierClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
GType _gtk_magnifier_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget * _gtk_magnifier_new (GtkWidget *inspected);
|
||||
|
||||
GtkWidget * _gtk_magnifier_get_inspected (GtkMagnifier *magnifier);
|
||||
void _gtk_magnifier_set_inspected (GtkMagnifier *magnifier,
|
||||
GtkWidget *inspected);
|
||||
|
||||
void _gtk_magnifier_set_coords (GtkMagnifier *magnifier,
|
||||
gdouble x,
|
||||
gdouble y);
|
||||
void _gtk_magnifier_get_coords (GtkMagnifier *magnifier,
|
||||
gdouble *x,
|
||||
gdouble *y);
|
||||
|
||||
void _gtk_magnifier_set_magnification (GtkMagnifier *magnifier,
|
||||
gdouble magnification);
|
||||
gdouble _gtk_magnifier_get_magnification (GtkMagnifier *magnifier);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_MAGNIFIER_H__ */
|
@ -1568,6 +1568,12 @@ gtk_main_do_event (GdkEvent *event)
|
||||
event_widget = gtk_get_event_widget (event);
|
||||
}
|
||||
|
||||
if (GTK_IS_WINDOW (event_widget))
|
||||
{
|
||||
if (_gtk_window_check_handle_wm_event (event))
|
||||
return;
|
||||
}
|
||||
|
||||
window_group = gtk_main_get_window_group (event_widget);
|
||||
device = gdk_event_get_device (event);
|
||||
|
||||
|
@ -396,6 +396,19 @@ blow_cache_cb (gpointer user_data)
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
context_is_unscaled (cairo_t *cr)
|
||||
{
|
||||
cairo_matrix_t matrix;
|
||||
gdouble x, y;
|
||||
|
||||
x = y = 1;
|
||||
cairo_get_matrix (cr, &matrix);
|
||||
cairo_matrix_transform_distance (&matrix, &x, &y);
|
||||
|
||||
return x == 1 && y == 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_gtk_pixel_cache_draw (GtkPixelCache *cache,
|
||||
@ -420,7 +433,7 @@ _gtk_pixel_cache_draw (GtkPixelCache *cache,
|
||||
_gtk_pixel_cache_set_position (cache, view_rect, canvas_rect);
|
||||
_gtk_pixel_cache_repaint (cache, draw, view_rect, canvas_rect, user_data);
|
||||
|
||||
if (cache->surface &&
|
||||
if (cache->surface && context_is_unscaled (cr) &&
|
||||
/* Don't use backing surface if rendering elsewhere */
|
||||
cairo_surface_get_type (cache->surface) == cairo_surface_get_type (cairo_get_target (cr)))
|
||||
{
|
||||
|
1679
gtk/gtkpopover.c
Normal file
1679
gtk/gtkpopover.c
Normal file
File diff suppressed because it is too large
Load Diff
84
gtk/gtkpopover.h
Normal file
84
gtk/gtkpopover.h
Normal file
@ -0,0 +1,84 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright © 2013 Carlos Garnacho <carlosg@gnome.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_POPOVER_H__
|
||||
#define __GTK_POPOVER_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtkwindow.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_POPOVER (gtk_popover_get_type ())
|
||||
#define GTK_POPOVER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_POPOVER, GtkPopover))
|
||||
#define GTK_POPOVER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GTK_TYPE_POPOVER, GtkPopoverClass))
|
||||
#define GTK_IS_POPOVER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_POPOVER))
|
||||
#define GTK_IS_POPOVER_CLASS(o) (G_TYPE_CHECK_CLASS_TYPE ((o), GTK_TYPE_POPOVER))
|
||||
#define GTK_POPOVER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_POPOVER, GtkPopoverClass))
|
||||
|
||||
typedef struct _GtkPopover GtkPopover;
|
||||
typedef struct _GtkPopoverClass GtkPopoverClass;
|
||||
|
||||
struct _GtkPopover
|
||||
{
|
||||
GtkBin parent_instance;
|
||||
|
||||
/*< private >*/
|
||||
gpointer priv;
|
||||
};
|
||||
|
||||
struct _GtkPopoverClass
|
||||
{
|
||||
GtkBinClass parent_class;
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_3_12
|
||||
GType gtk_popover_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_3_12
|
||||
GtkWidget * gtk_popover_new (GtkWidget *relative_to);
|
||||
|
||||
GDK_AVAILABLE_IN_3_12
|
||||
void gtk_popover_set_relative_to (GtkPopover *popover,
|
||||
GtkWidget *relative_to);
|
||||
GDK_AVAILABLE_IN_3_12
|
||||
GtkWidget * gtk_popover_get_relative_to (GtkPopover *popover);
|
||||
|
||||
GDK_AVAILABLE_IN_3_12
|
||||
void gtk_popover_set_pointing_to (GtkPopover *popover,
|
||||
cairo_rectangle_int_t *rect);
|
||||
GDK_AVAILABLE_IN_3_12
|
||||
gboolean gtk_popover_get_pointing_to (GtkPopover *popover,
|
||||
cairo_rectangle_int_t *rect);
|
||||
GDK_AVAILABLE_IN_3_12
|
||||
void gtk_popover_set_position (GtkPopover *popover,
|
||||
GtkPositionType position);
|
||||
GDK_AVAILABLE_IN_3_12
|
||||
GtkPositionType gtk_popover_get_position (GtkPopover *popover);
|
||||
|
||||
GDK_AVAILABLE_IN_3_12
|
||||
void gtk_popover_set_modal (GtkPopover *popover,
|
||||
gboolean modal);
|
||||
GDK_AVAILABLE_IN_3_12
|
||||
gboolean gtk_popover_get_modal (GtkPopover *popover);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_POPOVER_H__ */
|
@ -20,6 +20,7 @@
|
||||
#include "gtktexthandleprivate.h"
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkwindowprivate.h"
|
||||
#include "gtkintl.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
@ -35,13 +36,12 @@ enum {
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_PARENT,
|
||||
PROP_RELATIVE_TO
|
||||
PROP_PARENT
|
||||
};
|
||||
|
||||
struct _HandleWindow
|
||||
{
|
||||
GdkWindow *window;
|
||||
GtkWidget *widget;
|
||||
GdkRectangle pointing_to;
|
||||
gint dx;
|
||||
gint dy;
|
||||
@ -55,13 +55,11 @@ struct _GtkTextHandlePrivate
|
||||
{
|
||||
HandleWindow windows[2];
|
||||
GtkWidget *parent;
|
||||
GdkWindow *relative_to;
|
||||
|
||||
gulong draw_signal_id;
|
||||
gulong event_signal_id;
|
||||
gulong style_updated_id;
|
||||
gulong composited_changed_id;
|
||||
guint realized : 1;
|
||||
GtkScrollable *parent_scrollable;
|
||||
GtkAdjustment *vadj;
|
||||
GtkAdjustment *hadj;
|
||||
guint hierarchy_changed_id;
|
||||
guint scrollable_notify_id;
|
||||
guint mode : 2;
|
||||
};
|
||||
|
||||
@ -69,6 +67,9 @@ G_DEFINE_TYPE_WITH_PRIVATE (GtkTextHandle, _gtk_text_handle, G_TYPE_OBJECT)
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void _gtk_text_handle_update (GtkTextHandle *handle,
|
||||
GtkTextHandlePosition pos);
|
||||
|
||||
static void
|
||||
_gtk_text_handle_get_size (GtkTextHandle *handle,
|
||||
gint *width,
|
||||
@ -104,10 +105,6 @@ _gtk_text_handle_draw (GtkTextHandle *handle,
|
||||
|
||||
cairo_save (cr);
|
||||
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_rgba (cr, 0, 0, 0, 0);
|
||||
cairo_paint (cr);
|
||||
|
||||
if (pos == GTK_TEXT_HANDLE_POSITION_SELECTION_END)
|
||||
cairo_translate (cr, 0, priv->windows[pos].pointing_to.height);
|
||||
|
||||
@ -135,92 +132,18 @@ _gtk_text_handle_draw (GtkTextHandle *handle,
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_text_handle_update_shape (GtkTextHandle *handle,
|
||||
GdkWindow *window,
|
||||
GtkTextHandlePosition pos)
|
||||
static gint
|
||||
_text_handle_pos_from_widget (GtkTextHandle *handle,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkTextHandlePrivate *priv;
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_surface_t *surface;
|
||||
cairo_region_t *region;
|
||||
cairo_t *cr;
|
||||
GtkTextHandlePrivate *priv = handle->priv;
|
||||
|
||||
priv = handle->priv;
|
||||
|
||||
surface =
|
||||
gdk_window_create_similar_surface (window,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
gdk_window_get_width (window),
|
||||
gdk_window_get_height (window));
|
||||
|
||||
cr = cairo_create (surface);
|
||||
_gtk_text_handle_draw (handle, cr, pos);
|
||||
cairo_destroy (cr);
|
||||
|
||||
region = gdk_cairo_region_create_from_surface (surface);
|
||||
|
||||
if (gtk_widget_is_composited (priv->parent))
|
||||
gdk_window_shape_combine_region (window, NULL, 0, 0);
|
||||
if (widget == priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget)
|
||||
return GTK_TEXT_HANDLE_POSITION_SELECTION_START;
|
||||
else if (widget == priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget)
|
||||
return GTK_TEXT_HANDLE_POSITION_SELECTION_END;
|
||||
else
|
||||
gdk_window_shape_combine_region (window, region, 0, 0);
|
||||
|
||||
cairo_region_get_extents (region, &rect);
|
||||
cairo_region_destroy (region);
|
||||
|
||||
/* Preserve x/width, but extend input shape
|
||||
* vertically to all window height */
|
||||
rect.y = 0;
|
||||
rect.height = gdk_window_get_height (window);
|
||||
region = cairo_region_create_rectangle (&rect);
|
||||
|
||||
gdk_window_input_shape_combine_region (window, region, 0, 0);
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
cairo_region_destroy (region);
|
||||
}
|
||||
|
||||
static GdkWindow *
|
||||
_gtk_text_handle_create_window (GtkTextHandle *handle,
|
||||
GtkTextHandlePosition pos)
|
||||
{
|
||||
GtkTextHandlePrivate *priv;
|
||||
GdkRGBA bg = { 0, 0, 0, 0 };
|
||||
GdkWindowAttr attributes;
|
||||
GdkWindow *window;
|
||||
GdkVisual *visual;
|
||||
gint mask;
|
||||
|
||||
priv = handle->priv;
|
||||
|
||||
attributes.x = 0;
|
||||
attributes.y = 0;
|
||||
_gtk_text_handle_get_size (handle, &attributes.width, &attributes.height);
|
||||
attributes.window_type = GDK_WINDOW_TEMP;
|
||||
attributes.wclass = GDK_INPUT_OUTPUT;
|
||||
attributes.event_mask = (GDK_EXPOSURE_MASK |
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_BUTTON1_MOTION_MASK);
|
||||
|
||||
mask = GDK_WA_X | GDK_WA_Y;
|
||||
|
||||
visual = gdk_screen_get_rgba_visual (gtk_widget_get_screen (priv->parent));
|
||||
|
||||
if (visual)
|
||||
{
|
||||
attributes.visual = visual;
|
||||
mask |= GDK_WA_VISUAL;
|
||||
}
|
||||
|
||||
window = gdk_window_new (gtk_widget_get_root_window (priv->parent),
|
||||
&attributes, mask);
|
||||
gtk_widget_register_window (priv->parent, window);
|
||||
gdk_window_set_background_rgba (window, &bg);
|
||||
|
||||
_gtk_text_handle_update_shape (handle, window, pos);
|
||||
|
||||
return window;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -228,27 +151,15 @@ gtk_text_handle_widget_draw (GtkWidget *widget,
|
||||
cairo_t *cr,
|
||||
GtkTextHandle *handle)
|
||||
{
|
||||
GtkTextHandlePrivate *priv;
|
||||
GtkTextHandlePosition pos;
|
||||
HandleWindow *handle_window;
|
||||
gint pos;
|
||||
|
||||
priv = handle->priv;
|
||||
pos = _text_handle_pos_from_widget (handle, widget);
|
||||
|
||||
if (!priv->realized)
|
||||
if (pos < 0)
|
||||
return FALSE;
|
||||
|
||||
if (gtk_cairo_should_draw_window (cr, priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window))
|
||||
pos = GTK_TEXT_HANDLE_POSITION_SELECTION_START;
|
||||
else if (gtk_cairo_should_draw_window (cr, priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window))
|
||||
pos = GTK_TEXT_HANDLE_POSITION_SELECTION_END;
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
handle_window = &priv->windows[pos];
|
||||
if (gdk_window_is_visible (handle_window->window))
|
||||
_gtk_text_handle_draw (handle, cr, pos);
|
||||
|
||||
return FALSE;
|
||||
_gtk_text_handle_draw (handle, cr, pos);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -257,15 +168,12 @@ gtk_text_handle_widget_event (GtkWidget *widget,
|
||||
GtkTextHandle *handle)
|
||||
{
|
||||
GtkTextHandlePrivate *priv;
|
||||
GtkTextHandlePosition pos;
|
||||
gint pos;
|
||||
|
||||
priv = handle->priv;
|
||||
pos = _text_handle_pos_from_widget (handle, widget);
|
||||
|
||||
if (event->any.window == priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window)
|
||||
pos = GTK_TEXT_HANDLE_POSITION_SELECTION_START;
|
||||
else if (event->any.window == priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window)
|
||||
pos = GTK_TEXT_HANDLE_POSITION_SELECTION_END;
|
||||
else
|
||||
if (pos < 0)
|
||||
return FALSE;
|
||||
|
||||
if (event->type == GDK_BUTTON_PRESS)
|
||||
@ -277,24 +185,24 @@ gtk_text_handle_widget_event (GtkWidget *widget,
|
||||
else if (event->type == GDK_BUTTON_RELEASE)
|
||||
{
|
||||
g_signal_emit (handle, signals[DRAG_FINISHED], 0, pos);
|
||||
priv->windows[pos].dx = priv->windows[pos].dy = 0;
|
||||
priv->windows[pos].dragged = FALSE;
|
||||
}
|
||||
else if (event->type == GDK_MOTION_NOTIFY && priv->windows[pos].dragged)
|
||||
else if (event->type == GDK_MOTION_NOTIFY &&
|
||||
event->motion.state & GDK_BUTTON1_MASK &&
|
||||
priv->windows[pos].dragged)
|
||||
{
|
||||
gint x, y, width, height;
|
||||
|
||||
_gtk_text_handle_get_size (handle, &width, &height);
|
||||
gdk_window_get_origin (priv->relative_to, &x, &y);
|
||||
x = event->motion.x - priv->windows[pos].dx + (width / 2);
|
||||
y = event->motion.y - priv->windows[pos].dy;
|
||||
|
||||
x = event->motion.x_root - priv->windows[pos].dx + (width / 2) - x;
|
||||
y = event->motion.y_root - priv->windows[pos].dy - y;
|
||||
|
||||
if (pos == GTK_TEXT_HANDLE_POSITION_SELECTION_START)
|
||||
if (pos != GTK_TEXT_HANDLE_POSITION_CURSOR)
|
||||
y += height;
|
||||
|
||||
y += priv->windows[pos].pointing_to.height / 2;
|
||||
|
||||
gtk_widget_translate_coordinates (widget, priv->parent, x, y, &x, &y);
|
||||
g_signal_emit (handle, signals[HANDLE_DRAGGED], 0, pos, x, y);
|
||||
}
|
||||
|
||||
@ -302,8 +210,84 @@ gtk_text_handle_widget_event (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_text_handle_update_window_state (GtkTextHandle *handle,
|
||||
GtkTextHandlePosition pos)
|
||||
gtk_text_handle_widget_style_updated (GtkWidget *widget,
|
||||
GtkTextHandle *handle)
|
||||
{
|
||||
_gtk_text_handle_update (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START);
|
||||
_gtk_text_handle_update (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
_gtk_text_handle_ensure_widget (GtkTextHandle *handle,
|
||||
GtkTextHandlePosition pos)
|
||||
{
|
||||
GtkTextHandlePrivate *priv;
|
||||
|
||||
priv = handle->priv;
|
||||
|
||||
if (!priv->windows[pos].widget)
|
||||
{
|
||||
GtkWidget *widget, *window;
|
||||
|
||||
widget = gtk_event_box_new ();
|
||||
gtk_widget_set_events (widget,
|
||||
GDK_BUTTON_PRESS_MASK |
|
||||
GDK_BUTTON_RELEASE_MASK |
|
||||
GDK_POINTER_MOTION_MASK);
|
||||
|
||||
g_signal_connect (widget, "draw",
|
||||
G_CALLBACK (gtk_text_handle_widget_draw), handle);
|
||||
g_signal_connect (widget, "event",
|
||||
G_CALLBACK (gtk_text_handle_widget_event), handle);
|
||||
g_signal_connect (widget, "style-updated",
|
||||
G_CALLBACK (gtk_text_handle_widget_style_updated),
|
||||
handle);
|
||||
|
||||
priv->windows[pos].widget = g_object_ref_sink (widget);
|
||||
window = gtk_widget_get_ancestor (priv->parent, GTK_TYPE_WINDOW);
|
||||
_gtk_window_add_popover (GTK_WINDOW (window), widget);
|
||||
}
|
||||
|
||||
return priv->windows[pos].widget;
|
||||
}
|
||||
|
||||
static void
|
||||
_handle_update_child_visible (GtkTextHandle *handle,
|
||||
GtkTextHandlePosition pos)
|
||||
{
|
||||
HandleWindow *handle_window;
|
||||
GtkTextHandlePrivate *priv;
|
||||
cairo_rectangle_int_t rect;
|
||||
GtkAllocation allocation;
|
||||
GtkWidget *parent;
|
||||
|
||||
priv = handle->priv;
|
||||
handle_window = &priv->windows[pos];
|
||||
|
||||
if (!priv->parent_scrollable)
|
||||
{
|
||||
gtk_widget_set_child_visible (handle_window->widget, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
parent = gtk_widget_get_parent (GTK_WIDGET (priv->parent_scrollable));
|
||||
rect = handle_window->pointing_to;
|
||||
|
||||
gtk_widget_translate_coordinates (priv->parent, parent,
|
||||
rect.x, rect.y, &rect.x, &rect.y);
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (parent), &allocation);
|
||||
|
||||
if (rect.x < 0 || rect.x + rect.width > allocation.width ||
|
||||
rect.y < 0 || rect.y + rect.height > allocation.height)
|
||||
gtk_widget_set_child_visible (handle_window->widget, FALSE);
|
||||
else
|
||||
gtk_widget_set_child_visible (handle_window->widget, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_text_handle_update (GtkTextHandle *handle,
|
||||
GtkTextHandlePosition pos)
|
||||
{
|
||||
GtkTextHandlePrivate *priv;
|
||||
HandleWindow *handle_window;
|
||||
@ -311,93 +295,209 @@ _gtk_text_handle_update_window_state (GtkTextHandle *handle,
|
||||
priv = handle->priv;
|
||||
handle_window = &priv->windows[pos];
|
||||
|
||||
if (!handle_window->window)
|
||||
if (!priv->parent || !gtk_widget_is_drawable (priv->parent))
|
||||
return;
|
||||
|
||||
if (handle_window->has_point &&
|
||||
handle_window->mode_visible && handle_window->user_visible)
|
||||
{
|
||||
gint x, y, width, height;
|
||||
cairo_rectangle_int_t rect;
|
||||
GtkPositionType handle_pos;
|
||||
gint width, height;
|
||||
GtkWidget *window;
|
||||
|
||||
x = handle_window->pointing_to.x;
|
||||
y = handle_window->pointing_to.y;
|
||||
_gtk_text_handle_ensure_widget (handle, pos);
|
||||
_gtk_text_handle_get_size (handle, &width, &height);
|
||||
rect.x = handle_window->pointing_to.x;
|
||||
rect.y = handle_window->pointing_to.y;
|
||||
rect.width = width;
|
||||
rect.height = 0;
|
||||
|
||||
if (pos != GTK_TEXT_HANDLE_POSITION_CURSOR)
|
||||
y -= height;
|
||||
_handle_update_child_visible (handle, pos);
|
||||
|
||||
window = gtk_widget_get_parent (handle_window->widget);
|
||||
gtk_widget_translate_coordinates (priv->parent, window,
|
||||
rect.x, rect.y, &rect.x, &rect.y);
|
||||
|
||||
if (pos == GTK_TEXT_HANDLE_POSITION_CURSOR)
|
||||
handle_pos = GTK_POS_BOTTOM;
|
||||
else
|
||||
{
|
||||
handle_pos = GTK_POS_TOP;
|
||||
rect.y += handle_window->pointing_to.height;
|
||||
}
|
||||
|
||||
height += handle_window->pointing_to.height;
|
||||
x -= width / 2;
|
||||
rect.x -= rect.width / 2;
|
||||
|
||||
gdk_window_move_resize (handle_window->window, x, y, width, height);
|
||||
gdk_window_show (handle_window->window);
|
||||
gtk_widget_set_size_request (handle_window->widget, width, height);
|
||||
gtk_widget_show (handle_window->widget);
|
||||
_gtk_window_set_popover_position (GTK_WINDOW (window),
|
||||
handle_window->widget,
|
||||
handle_pos, &rect);
|
||||
}
|
||||
else
|
||||
gdk_window_hide (handle_window->window);
|
||||
else if (handle_window->widget)
|
||||
gtk_widget_hide (handle_window->widget);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_text_handle_update_window (GtkTextHandle *handle,
|
||||
GtkTextHandlePosition pos,
|
||||
gboolean recreate)
|
||||
adjustment_changed_cb (GtkAdjustment *adjustment,
|
||||
GtkTextHandle *handle)
|
||||
{
|
||||
_gtk_text_handle_update (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START);
|
||||
_gtk_text_handle_update (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_text_handle_set_scrollable (GtkTextHandle *handle,
|
||||
GtkScrollable *scrollable)
|
||||
{
|
||||
GtkTextHandlePrivate *priv;
|
||||
HandleWindow *handle_window;
|
||||
|
||||
priv = handle->priv;
|
||||
handle_window = &priv->windows[pos];
|
||||
|
||||
if (!handle_window->window)
|
||||
return;
|
||||
|
||||
if (recreate)
|
||||
if (priv->parent_scrollable)
|
||||
{
|
||||
gtk_widget_unregister_window (priv->parent, handle_window->window);
|
||||
gdk_window_destroy (handle_window->window);
|
||||
handle_window->window = _gtk_text_handle_create_window (handle, pos);
|
||||
if (priv->vadj)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_data (priv->vadj, handle);
|
||||
g_object_unref (priv->vadj);
|
||||
priv->vadj = NULL;
|
||||
}
|
||||
|
||||
if (priv->hadj)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_data (priv->hadj, handle);
|
||||
g_object_unref (priv->hadj);
|
||||
priv->hadj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
_gtk_text_handle_update_window_state (handle, pos);
|
||||
priv->parent_scrollable = scrollable;
|
||||
|
||||
if (scrollable)
|
||||
{
|
||||
priv->vadj = gtk_scrollable_get_vadjustment (scrollable);
|
||||
priv->hadj = gtk_scrollable_get_hadjustment (scrollable);
|
||||
|
||||
if (priv->vadj)
|
||||
{
|
||||
g_object_ref (priv->vadj);
|
||||
g_signal_connect (priv->vadj, "changed",
|
||||
G_CALLBACK (adjustment_changed_cb), handle);
|
||||
g_signal_connect (priv->vadj, "value-changed",
|
||||
G_CALLBACK (adjustment_changed_cb), handle);
|
||||
}
|
||||
|
||||
if (priv->hadj)
|
||||
{
|
||||
g_object_ref (priv->hadj);
|
||||
g_signal_connect (priv->hadj, "changed",
|
||||
G_CALLBACK (adjustment_changed_cb), handle);
|
||||
g_signal_connect (priv->hadj, "value-changed",
|
||||
G_CALLBACK (adjustment_changed_cb), handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_text_handle_update_windows (GtkTextHandle *handle)
|
||||
_gtk_text_handle_scrollable_notify (GObject *object,
|
||||
GParamSpec *pspec,
|
||||
GtkTextHandle *handle)
|
||||
{
|
||||
_gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START, FALSE);
|
||||
_gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END, FALSE);
|
||||
if (pspec->value_type == GTK_TYPE_ADJUSTMENT)
|
||||
_gtk_text_handle_set_scrollable (handle, GTK_SCROLLABLE (object));
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_text_handle_composited_changed (GtkTextHandle *handle)
|
||||
{
|
||||
_gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START, TRUE);
|
||||
_gtk_text_handle_update_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_handle_constructed (GObject *object)
|
||||
_gtk_text_handle_update_scrollable (GtkTextHandle *handle,
|
||||
GtkScrollable *scrollable)
|
||||
{
|
||||
GtkTextHandlePrivate *priv;
|
||||
|
||||
priv = GTK_TEXT_HANDLE (object)->priv;
|
||||
g_assert (priv->parent != NULL);
|
||||
priv = handle->priv;
|
||||
|
||||
priv->draw_signal_id =
|
||||
g_signal_connect (priv->parent, "draw",
|
||||
G_CALLBACK (gtk_text_handle_widget_draw),
|
||||
object);
|
||||
priv->event_signal_id =
|
||||
g_signal_connect (priv->parent, "event",
|
||||
G_CALLBACK (gtk_text_handle_widget_event),
|
||||
object);
|
||||
priv->composited_changed_id =
|
||||
g_signal_connect_swapped (priv->parent, "composited-changed",
|
||||
G_CALLBACK (_gtk_text_handle_composited_changed),
|
||||
object);
|
||||
priv->style_updated_id =
|
||||
g_signal_connect_swapped (priv->parent, "style-updated",
|
||||
G_CALLBACK (_gtk_text_handle_update_windows),
|
||||
object);
|
||||
if (priv->parent_scrollable == scrollable)
|
||||
return;
|
||||
|
||||
if (priv->parent_scrollable && priv->scrollable_notify_id &&
|
||||
g_signal_handler_is_connected (priv->parent_scrollable,
|
||||
priv->scrollable_notify_id))
|
||||
g_signal_handler_disconnect (priv->parent_scrollable,
|
||||
priv->scrollable_notify_id);
|
||||
|
||||
_gtk_text_handle_set_scrollable (handle, scrollable);
|
||||
|
||||
if (priv->parent_scrollable)
|
||||
priv->scrollable_notify_id =
|
||||
g_signal_connect (priv->parent_scrollable, "notify",
|
||||
G_CALLBACK (_gtk_text_handle_scrollable_notify),
|
||||
handle);
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_text_handle_parent_hierarchy_changed (GtkWidget *widget,
|
||||
GtkWindow *previous_toplevel,
|
||||
GtkTextHandle *handle)
|
||||
{
|
||||
GtkWidget *toplevel, *scrollable;
|
||||
GtkTextHandlePrivate *priv;
|
||||
|
||||
priv = handle->priv;
|
||||
toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
|
||||
|
||||
if (previous_toplevel && !toplevel)
|
||||
{
|
||||
if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget)
|
||||
{
|
||||
_gtk_window_remove_popover (GTK_WINDOW (previous_toplevel),
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget);
|
||||
g_object_unref (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget);
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget = NULL;
|
||||
}
|
||||
|
||||
if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget)
|
||||
{
|
||||
_gtk_window_remove_popover (GTK_WINDOW (previous_toplevel),
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget);
|
||||
g_object_unref (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget);
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
scrollable = gtk_widget_get_ancestor (widget, GTK_TYPE_SCROLLABLE);
|
||||
_gtk_text_handle_update_scrollable (handle, GTK_SCROLLABLE (scrollable));
|
||||
}
|
||||
|
||||
static void
|
||||
_gtk_text_handle_set_parent (GtkTextHandle *handle,
|
||||
GtkWidget *parent)
|
||||
{
|
||||
GtkTextHandlePrivate *priv;
|
||||
GtkWidget *scrollable = NULL;
|
||||
|
||||
priv = handle->priv;
|
||||
|
||||
if (priv->parent == parent)
|
||||
return;
|
||||
|
||||
if (priv->parent && priv->hierarchy_changed_id &&
|
||||
g_signal_handler_is_connected (priv->parent, priv->hierarchy_changed_id))
|
||||
g_signal_handler_disconnect (priv->parent, priv->hierarchy_changed_id);
|
||||
|
||||
priv->parent = parent;
|
||||
|
||||
if (parent)
|
||||
{
|
||||
priv->hierarchy_changed_id =
|
||||
g_signal_connect (parent, "hierarchy-changed",
|
||||
G_CALLBACK (_gtk_text_handle_parent_hierarchy_changed),
|
||||
handle);
|
||||
|
||||
scrollable = gtk_widget_get_ancestor (parent, GTK_TYPE_SCROLLABLE);
|
||||
}
|
||||
|
||||
_gtk_text_handle_update_scrollable (handle, GTK_SCROLLABLE (scrollable));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -407,34 +507,14 @@ gtk_text_handle_finalize (GObject *object)
|
||||
|
||||
priv = GTK_TEXT_HANDLE (object)->priv;
|
||||
|
||||
if (priv->relative_to)
|
||||
g_object_unref (priv->relative_to);
|
||||
_gtk_text_handle_set_parent (GTK_TEXT_HANDLE (object), NULL);
|
||||
|
||||
if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window)
|
||||
{
|
||||
gtk_widget_unregister_window (priv->parent,
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
|
||||
gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
|
||||
}
|
||||
/* We sank the references, unref here */
|
||||
if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget)
|
||||
g_object_unref (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].widget);
|
||||
|
||||
if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window)
|
||||
{
|
||||
gtk_widget_unregister_window (priv->parent,
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
|
||||
gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
|
||||
}
|
||||
|
||||
if (g_signal_handler_is_connected (priv->parent, priv->draw_signal_id))
|
||||
g_signal_handler_disconnect (priv->parent, priv->draw_signal_id);
|
||||
|
||||
if (g_signal_handler_is_connected (priv->parent, priv->event_signal_id))
|
||||
g_signal_handler_disconnect (priv->parent, priv->event_signal_id);
|
||||
|
||||
if (g_signal_handler_is_connected (priv->parent, priv->composited_changed_id))
|
||||
g_signal_handler_disconnect (priv->parent, priv->composited_changed_id);
|
||||
|
||||
if (g_signal_handler_is_connected (priv->parent, priv->style_updated_id))
|
||||
g_signal_handler_disconnect (priv->parent, priv->style_updated_id);
|
||||
if (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget)
|
||||
g_object_unref (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].widget);
|
||||
|
||||
G_OBJECT_CLASS (_gtk_text_handle_parent_class)->finalize (object);
|
||||
}
|
||||
@ -445,20 +525,14 @@ gtk_text_handle_set_property (GObject *object,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkTextHandlePrivate *priv;
|
||||
GtkTextHandle *handle;
|
||||
|
||||
handle = GTK_TEXT_HANDLE (object);
|
||||
priv = handle->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_PARENT:
|
||||
priv->parent = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_RELATIVE_TO:
|
||||
_gtk_text_handle_set_relative_to (handle,
|
||||
g_value_get_object (value));
|
||||
_gtk_text_handle_set_parent (handle, g_value_get_object (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
@ -480,9 +554,6 @@ gtk_text_handle_get_property (GObject *object,
|
||||
case PROP_PARENT:
|
||||
g_value_set_object (value, priv->parent);
|
||||
break;
|
||||
case PROP_RELATIVE_TO:
|
||||
g_value_set_object (value, priv->relative_to);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
@ -493,7 +564,6 @@ _gtk_text_handle_class_init (GtkTextHandleClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = gtk_text_handle_constructed;
|
||||
object_class->finalize = gtk_text_handle_finalize;
|
||||
object_class->set_property = gtk_text_handle_set_property;
|
||||
object_class->get_property = gtk_text_handle_get_property;
|
||||
@ -525,13 +595,6 @@ _gtk_text_handle_class_init (GtkTextHandleClass *klass)
|
||||
GTK_TYPE_WIDGET,
|
||||
GTK_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_RELATIVE_TO,
|
||||
g_param_spec_object ("relative-to",
|
||||
P_("Window"),
|
||||
P_("Window the coordinates are based upon"),
|
||||
GDK_TYPE_WINDOW,
|
||||
GTK_PARAM_READWRITE));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -548,48 +611,6 @@ _gtk_text_handle_new (GtkWidget *parent)
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_text_handle_set_relative_to (GtkTextHandle *handle,
|
||||
GdkWindow *window)
|
||||
{
|
||||
GtkTextHandlePrivate *priv;
|
||||
|
||||
g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
|
||||
g_return_if_fail (!window || GDK_IS_WINDOW (window));
|
||||
|
||||
priv = handle->priv;
|
||||
|
||||
if (priv->relative_to)
|
||||
{
|
||||
gtk_widget_unregister_window (priv->parent,
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
|
||||
gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window);
|
||||
gtk_widget_unregister_window (priv->parent,
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
|
||||
gdk_window_destroy (priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window);
|
||||
g_object_unref (priv->relative_to);
|
||||
}
|
||||
|
||||
if (window)
|
||||
{
|
||||
priv->relative_to = g_object_ref (window);
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window =
|
||||
_gtk_text_handle_create_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START);
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window =
|
||||
_gtk_text_handle_create_window (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END);
|
||||
priv->realized = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window = NULL;
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_END].window = NULL;
|
||||
priv->relative_to = NULL;
|
||||
priv->realized = FALSE;
|
||||
}
|
||||
|
||||
g_object_notify (G_OBJECT (handle), "relative-to");
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_text_handle_set_mode (GtkTextHandle *handle,
|
||||
GtkTextHandleMode mode)
|
||||
@ -622,15 +643,8 @@ _gtk_text_handle_set_mode (GtkTextHandle *handle,
|
||||
break;
|
||||
}
|
||||
|
||||
_gtk_text_handle_update_shape (handle,
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_CURSOR].window,
|
||||
GTK_TEXT_HANDLE_POSITION_CURSOR);
|
||||
_gtk_text_handle_update_shape (handle,
|
||||
priv->windows[GTK_TEXT_HANDLE_POSITION_SELECTION_START].window,
|
||||
GTK_TEXT_HANDLE_POSITION_SELECTION_START);
|
||||
|
||||
_gtk_text_handle_update_window_state (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START);
|
||||
_gtk_text_handle_update_window_state (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END);
|
||||
_gtk_text_handle_update (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_START);
|
||||
_gtk_text_handle_update (handle, GTK_TEXT_HANDLE_POSITION_SELECTION_END);
|
||||
}
|
||||
|
||||
GtkTextHandleMode
|
||||
@ -651,7 +665,6 @@ _gtk_text_handle_set_position (GtkTextHandle *handle,
|
||||
{
|
||||
GtkTextHandlePrivate *priv;
|
||||
HandleWindow *handle_window;
|
||||
gboolean size_changed;
|
||||
|
||||
g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
|
||||
|
||||
@ -660,28 +673,16 @@ _gtk_text_handle_set_position (GtkTextHandle *handle,
|
||||
GTK_TEXT_HANDLE_POSITION_SELECTION_START);
|
||||
handle_window = &priv->windows[pos];
|
||||
|
||||
if (!priv->realized)
|
||||
return;
|
||||
|
||||
if (priv->mode == GTK_TEXT_HANDLE_MODE_NONE ||
|
||||
(priv->mode == GTK_TEXT_HANDLE_MODE_CURSOR &&
|
||||
pos != GTK_TEXT_HANDLE_POSITION_CURSOR))
|
||||
return;
|
||||
|
||||
size_changed = (rect->width != handle_window->pointing_to.width ||
|
||||
rect->height != handle_window->pointing_to.height);
|
||||
|
||||
handle_window->pointing_to = *rect;
|
||||
handle_window->has_point = TRUE;
|
||||
gdk_window_get_root_coords (priv->relative_to,
|
||||
rect->x, rect->y,
|
||||
&handle_window->pointing_to.x,
|
||||
&handle_window->pointing_to.y);
|
||||
|
||||
_gtk_text_handle_update_window_state (handle, pos);
|
||||
|
||||
if (size_changed)
|
||||
_gtk_text_handle_update_shape (handle, handle_window->window, pos);
|
||||
if (gtk_widget_is_visible (priv->parent))
|
||||
_gtk_text_handle_update (handle, pos);
|
||||
}
|
||||
|
||||
void
|
||||
@ -690,7 +691,6 @@ _gtk_text_handle_set_visible (GtkTextHandle *handle,
|
||||
gboolean visible)
|
||||
{
|
||||
GtkTextHandlePrivate *priv;
|
||||
GdkWindow *window;
|
||||
|
||||
g_return_if_fail (GTK_IS_TEXT_HANDLE (handle));
|
||||
|
||||
@ -698,19 +698,10 @@ _gtk_text_handle_set_visible (GtkTextHandle *handle,
|
||||
pos = CLAMP (pos, GTK_TEXT_HANDLE_POSITION_CURSOR,
|
||||
GTK_TEXT_HANDLE_POSITION_SELECTION_START);
|
||||
|
||||
if (!priv->realized)
|
||||
return;
|
||||
|
||||
window = priv->windows[pos].window;
|
||||
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!gdk_window_is_visible (window))
|
||||
_gtk_text_handle_update_shape (handle, window, pos);
|
||||
|
||||
priv->windows[pos].user_visible = visible;
|
||||
_gtk_text_handle_update_window_state (handle, pos);
|
||||
|
||||
if (gtk_widget_is_visible (priv->parent))
|
||||
_gtk_text_handle_update (handle, pos);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -51,9 +51,10 @@
|
||||
#include "gtktexthandleprivate.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkcssstylepropertyprivate.h"
|
||||
#include "gtkbubblewindowprivate.h"
|
||||
#include "gtkpopover.h"
|
||||
#include "gtktoolbar.h"
|
||||
#include "gtkpixelcacheprivate.h"
|
||||
#include "gtkmagnifierprivate.h"
|
||||
|
||||
#include "a11y/gtktextviewaccessibleprivate.h"
|
||||
|
||||
@ -140,6 +141,9 @@ struct _GtkTextViewPrivate
|
||||
GtkWidget *selection_bubble;
|
||||
guint selection_bubble_timeout_id;
|
||||
|
||||
GtkWidget *magnifier_popover;
|
||||
GtkWidget *magnifier;
|
||||
|
||||
GtkTextWindow *text_window;
|
||||
GtkTextWindow *left_window;
|
||||
GtkTextWindow *right_window;
|
||||
@ -1542,6 +1546,18 @@ gtk_text_view_init (GtkTextView *text_view)
|
||||
G_CALLBACK (gtk_text_view_handle_dragged), text_view);
|
||||
g_signal_connect (priv->text_handle, "drag-finished",
|
||||
G_CALLBACK (gtk_text_view_handle_drag_finished), text_view);
|
||||
|
||||
priv->magnifier = _gtk_magnifier_new (widget);
|
||||
gtk_widget_set_size_request (priv->magnifier, 100, 60);
|
||||
_gtk_magnifier_set_magnification (GTK_MAGNIFIER (priv->magnifier), 2.0);
|
||||
priv->magnifier_popover = gtk_popover_new (widget);
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (priv->magnifier_popover),
|
||||
GTK_STYLE_CLASS_OSD);
|
||||
gtk_popover_set_modal (GTK_POPOVER (priv->magnifier_popover), FALSE);
|
||||
gtk_container_add (GTK_CONTAINER (priv->magnifier_popover),
|
||||
priv->magnifier);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (priv->magnifier_popover), 4);
|
||||
gtk_widget_show (priv->magnifier);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -3215,6 +3231,7 @@ gtk_text_view_finalize (GObject *object)
|
||||
if (priv->selection_bubble)
|
||||
gtk_widget_destroy (priv->selection_bubble);
|
||||
|
||||
gtk_widget_destroy (priv->magnifier_popover);
|
||||
g_object_unref (priv->text_handle);
|
||||
g_object_unref (priv->im_context);
|
||||
|
||||
@ -4237,8 +4254,6 @@ gtk_text_view_realize (GtkWidget *widget)
|
||||
|
||||
/* Ensure updating the spot location. */
|
||||
gtk_text_view_update_im_spot_location (text_view);
|
||||
|
||||
_gtk_text_handle_set_relative_to (priv->text_handle, priv->text_window->window);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -4279,8 +4294,6 @@ gtk_text_view_unrealize (GtkWidget *widget)
|
||||
if (priv->bottom_window)
|
||||
text_window_unrealize (priv->bottom_window);
|
||||
|
||||
_gtk_text_handle_set_relative_to (priv->text_handle, NULL);
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_text_view_parent_class)->unrealize (widget);
|
||||
}
|
||||
|
||||
@ -4588,6 +4601,30 @@ gtk_text_view_set_handle_position (GtkTextView *text_view,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_view_show_magnifier (GtkTextView *text_view,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
GtkTextViewPrivate *priv;
|
||||
GtkAllocation allocation;
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (text_view), &allocation);
|
||||
|
||||
priv = text_view->priv;
|
||||
x = CLAMP (x, 0, allocation.width);
|
||||
y = CLAMP (y, 0, allocation.height);
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
rect.width = rect.height = 1;
|
||||
|
||||
_gtk_magnifier_set_coords (GTK_MAGNIFIER (priv->magnifier), x, y);
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (priv->magnifier_popover),
|
||||
&rect);
|
||||
gtk_widget_show (priv->magnifier_popover);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_text_view_handle_dragged (GtkTextHandle *handle,
|
||||
GtkTextHandlePosition pos,
|
||||
@ -4672,6 +4709,8 @@ gtk_text_view_handle_dragged (GtkTextHandle *handle,
|
||||
gtk_text_view_scroll_mark_onscreen (text_view,
|
||||
gtk_text_buffer_get_selection_bound (buffer));
|
||||
}
|
||||
|
||||
gtk_text_view_show_magnifier (text_view, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -4680,6 +4719,7 @@ gtk_text_view_handle_drag_finished (GtkTextHandle *handle,
|
||||
GtkTextView *text_view)
|
||||
{
|
||||
gtk_text_view_selection_bubble_popup_set (text_view);
|
||||
gtk_widget_hide (text_view->priv->magnifier_popover);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -6948,7 +6988,10 @@ selection_motion_event_handler (GtkTextView *text_view,
|
||||
g_source_set_name_by_id (text_view->priv->scroll_timeout, "[gtk+] selection_scan_timeout");
|
||||
|
||||
if (test_touchscreen || input_source == GDK_SOURCE_TOUCHSCREEN)
|
||||
gtk_text_view_update_handles (text_view, GTK_TEXT_HANDLE_MODE_SELECTION);
|
||||
{
|
||||
gtk_text_view_update_handles (text_view, GTK_TEXT_HANDLE_MODE_SELECTION);
|
||||
gtk_text_view_show_magnifier (text_view, event->x, event->y);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -7068,6 +7111,8 @@ gtk_text_view_end_selection_drag (GtkTextView *text_view)
|
||||
priv->grab_device);
|
||||
priv->grab_device = NULL;
|
||||
|
||||
gtk_widget_hide (priv->magnifier_popover);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -8857,7 +8902,7 @@ activate_bubble_cb (GtkWidget *item,
|
||||
{
|
||||
const gchar *signal = g_object_get_data (G_OBJECT (item), "gtk-signal");
|
||||
g_signal_emit_by_name (text_view, signal);
|
||||
_gtk_bubble_window_popdown (GTK_BUBBLE_WINDOW (text_view->priv->selection_bubble));
|
||||
gtk_widget_hide (text_view->priv->selection_bubble);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -8868,6 +8913,7 @@ append_bubble_action (GtkTextView *text_view,
|
||||
gboolean sensitive)
|
||||
{
|
||||
GtkToolItem *item = gtk_tool_button_new (NULL, label);
|
||||
gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (item), TRUE);
|
||||
g_object_set_data (G_OBJECT (item), I_("gtk-signal"), (char *)signal);
|
||||
g_signal_connect (item, "clicked", G_CALLBACK (activate_bubble_cb), text_view);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (item), sensitive);
|
||||
@ -8888,7 +8934,6 @@ bubble_targets_received (GtkClipboard *clipboard,
|
||||
gboolean can_insert;
|
||||
GtkTextIter iter;
|
||||
GtkTextIter sel_start, sel_end;
|
||||
GdkWindow *window;
|
||||
GtkWidget *toolbar;
|
||||
|
||||
has_selection = gtk_text_buffer_get_selection_bounds (get_buffer (text_view),
|
||||
@ -8902,8 +8947,13 @@ bubble_targets_received (GtkClipboard *clipboard,
|
||||
if (priv->selection_bubble)
|
||||
gtk_widget_destroy (priv->selection_bubble);
|
||||
|
||||
window = gtk_widget_get_window (GTK_WIDGET (text_view));
|
||||
priv->selection_bubble = _gtk_bubble_window_new ();
|
||||
priv->selection_bubble = gtk_popover_new (GTK_WIDGET (text_view));
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (priv->selection_bubble),
|
||||
GTK_STYLE_CLASS_OSD);
|
||||
gtk_popover_set_position (GTK_POPOVER (priv->selection_bubble),
|
||||
GTK_POS_TOP);
|
||||
gtk_popover_set_modal (GTK_POPOVER (priv->selection_bubble), FALSE);
|
||||
|
||||
toolbar = GTK_WIDGET (gtk_toolbar_new ());
|
||||
gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_TEXT);
|
||||
gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), FALSE);
|
||||
@ -8930,8 +8980,9 @@ bubble_targets_received (GtkClipboard *clipboard,
|
||||
gtk_text_view_get_selection_rect (text_view, &rect);
|
||||
rect.x -= priv->xoffset;
|
||||
rect.y -= priv->yoffset;
|
||||
_gtk_bubble_window_popup (GTK_BUBBLE_WINDOW (priv->selection_bubble),
|
||||
window, &rect, GTK_POS_TOP);
|
||||
|
||||
gtk_popover_set_pointing_to (GTK_POPOVER (priv->selection_bubble), &rect);
|
||||
gtk_widget_show (priv->selection_bubble);
|
||||
|
||||
priv->selection_bubble_timeout_id = 0;
|
||||
}
|
||||
@ -8957,7 +9008,7 @@ gtk_text_view_selection_bubble_popup_unset (GtkTextView *text_view)
|
||||
priv = text_view->priv;
|
||||
|
||||
if (priv->selection_bubble)
|
||||
_gtk_bubble_window_popdown (GTK_BUBBLE_WINDOW (priv->selection_bubble));
|
||||
gtk_widget_hide (priv->selection_bubble);
|
||||
|
||||
if (priv->selection_bubble_timeout_id)
|
||||
{
|
||||
@ -9221,7 +9272,7 @@ text_window_scroll (GtkTextWindow *win,
|
||||
if (dx != 0 || dy != 0)
|
||||
{
|
||||
if (priv->selection_bubble)
|
||||
_gtk_bubble_window_popdown (GTK_BUBBLE_WINDOW (priv->selection_bubble));
|
||||
gtk_widget_hide (priv->selection_bubble);
|
||||
view->priv->in_scroll = TRUE;
|
||||
gdk_window_scroll (win->bin_window, dx, dy);
|
||||
view->priv->in_scroll = FALSE;
|
||||
|
449
gtk/gtkwindow.c
449
gtk/gtkwindow.c
@ -123,6 +123,16 @@
|
||||
#define MNEMONICS_DELAY 300 /* ms */
|
||||
|
||||
typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo;
|
||||
typedef struct _GtkWindowPopover GtkWindowPopover;
|
||||
|
||||
struct _GtkWindowPopover
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GdkWindow *window;
|
||||
GtkPositionType pos;
|
||||
cairo_rectangle_int_t rect;
|
||||
gulong unmap_id;
|
||||
};
|
||||
|
||||
struct _GtkWindowPrivate
|
||||
{
|
||||
@ -137,6 +147,8 @@ struct _GtkWindowPrivate
|
||||
GdkScreen *screen;
|
||||
GtkApplication *application;
|
||||
|
||||
GList *popovers;
|
||||
|
||||
GdkModifierType mnemonic_modifier;
|
||||
GdkWindowTypeHint gdk_type_hint;
|
||||
|
||||
@ -1318,6 +1330,24 @@ gtk_window_close (GtkWindow *window)
|
||||
gdk_threads_add_idle (send_delete_event, window);
|
||||
}
|
||||
|
||||
static void
|
||||
popover_destroy (GtkWindowPopover *popover)
|
||||
{
|
||||
if (popover->unmap_id)
|
||||
{
|
||||
g_signal_handler_disconnect (popover->widget, popover->unmap_id);
|
||||
popover->unmap_id = 0;
|
||||
}
|
||||
|
||||
if (popover->widget && gtk_widget_get_parent (popover->widget))
|
||||
gtk_widget_unparent (popover->widget);
|
||||
|
||||
if (popover->window)
|
||||
gdk_window_destroy (popover->window);
|
||||
|
||||
g_free (popover);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_init (GtkWindow *window)
|
||||
{
|
||||
@ -2630,6 +2660,16 @@ static void
|
||||
gtk_window_dispose (GObject *object)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (object);
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
|
||||
while (priv->popovers)
|
||||
{
|
||||
GtkWindowPopover *popover;
|
||||
|
||||
popover = priv->popovers->data;
|
||||
priv->popovers = g_list_remove_link (priv->popovers, priv->popovers);
|
||||
popover_destroy (popover);
|
||||
}
|
||||
|
||||
gtk_window_set_focus (window, NULL);
|
||||
gtk_window_set_default (window, NULL);
|
||||
@ -5398,6 +5438,41 @@ gtk_window_hide (GtkWidget *widget)
|
||||
gtk_grab_remove (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
popover_unmap (GtkWidget *widget,
|
||||
GtkWindowPopover *popover)
|
||||
{
|
||||
if (popover->window)
|
||||
{
|
||||
if (gtk_widget_is_visible (popover->widget))
|
||||
gtk_widget_unmap (popover->widget);
|
||||
gdk_window_hide (popover->window);
|
||||
}
|
||||
|
||||
if (popover->unmap_id)
|
||||
{
|
||||
g_signal_handler_disconnect (widget, popover->unmap_id);
|
||||
popover->unmap_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
popover_map (GtkWidget *widget,
|
||||
GtkWindowPopover *popover)
|
||||
{
|
||||
if (popover->window)
|
||||
{
|
||||
gdk_window_show (popover->window);
|
||||
|
||||
if (gtk_widget_get_visible (popover->widget))
|
||||
{
|
||||
gtk_widget_map (popover->widget);
|
||||
popover->unmap_id = g_signal_connect (popover->widget, "unmap",
|
||||
G_CALLBACK (popover_unmap), popover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_map (GtkWidget *widget)
|
||||
{
|
||||
@ -5405,6 +5480,7 @@ gtk_window_map (GtkWidget *widget)
|
||||
GtkWindow *window = GTK_WINDOW (widget);
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
GdkWindow *gdk_window;
|
||||
GList *link;
|
||||
|
||||
if (!gtk_widget_is_toplevel (widget))
|
||||
{
|
||||
@ -5511,6 +5587,15 @@ gtk_window_map (GtkWidget *widget)
|
||||
|
||||
if (priv->application)
|
||||
gtk_application_handle_window_map (priv->application, window);
|
||||
|
||||
link = priv->popovers;
|
||||
|
||||
while (link)
|
||||
{
|
||||
GtkWindowPopover *popover = link->data;
|
||||
link = link->next;
|
||||
popover_map (popover->widget, popover);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -5540,6 +5625,7 @@ gtk_window_unmap (GtkWidget *widget)
|
||||
GtkWindowGeometryInfo *info;
|
||||
GdkWindow *gdk_window;
|
||||
GdkWindowState state;
|
||||
GList *link;
|
||||
|
||||
if (!gtk_widget_is_toplevel (GTK_WIDGET (widget)))
|
||||
{
|
||||
@ -5547,6 +5633,15 @@ gtk_window_unmap (GtkWidget *widget)
|
||||
return;
|
||||
}
|
||||
|
||||
link = priv->popovers;
|
||||
|
||||
while (link)
|
||||
{
|
||||
GtkWindowPopover *popover = link->data;
|
||||
link = link->next;
|
||||
popover_unmap (popover->widget, popover);
|
||||
}
|
||||
|
||||
gdk_window = gtk_widget_get_window (widget);
|
||||
|
||||
gtk_widget_set_mapped (widget, FALSE);
|
||||
@ -5676,6 +5771,118 @@ gtk_window_get_remembered_size (GtkWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
popover_get_rect (GtkWindowPopover *popover,
|
||||
GtkWindow *window,
|
||||
cairo_rectangle_int_t *rect)
|
||||
{
|
||||
GtkAllocation win_alloc;
|
||||
GtkRequisition req;
|
||||
|
||||
gtk_widget_get_preferred_size (popover->widget, NULL, &req);
|
||||
gtk_widget_get_allocation (GTK_WIDGET (window), &win_alloc);
|
||||
rect->width = req.width;
|
||||
rect->height = req.height;
|
||||
|
||||
if (popover->pos == GTK_POS_LEFT || popover->pos == GTK_POS_RIGHT)
|
||||
{
|
||||
if (req.height < win_alloc.height &&
|
||||
gtk_widget_get_vexpand (popover->widget))
|
||||
{
|
||||
rect->y = 0;
|
||||
rect->height = win_alloc.height;
|
||||
}
|
||||
else
|
||||
rect->y = CLAMP (popover->rect.y + (popover->rect.height / 2) -
|
||||
(req.height / 2), 0, win_alloc.height - req.height);
|
||||
|
||||
if ((popover->pos == GTK_POS_LEFT) ==
|
||||
(gtk_widget_get_direction (popover->widget) == GTK_TEXT_DIR_LTR))
|
||||
{
|
||||
rect->x = popover->rect.x - req.width;
|
||||
|
||||
if (rect->x > 0 && gtk_widget_get_hexpand (popover->widget))
|
||||
{
|
||||
rect->x = 0;
|
||||
rect->width = popover->rect.x;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rect->x = popover->rect.x + popover->rect.width;
|
||||
|
||||
if (rect->x + rect->width < win_alloc.width &&
|
||||
gtk_widget_get_hexpand (popover->widget))
|
||||
rect->width = win_alloc.width - rect->x;
|
||||
}
|
||||
}
|
||||
else if (popover->pos == GTK_POS_TOP || popover->pos == GTK_POS_BOTTOM)
|
||||
{
|
||||
if (req.width < win_alloc.width &&
|
||||
gtk_widget_get_hexpand (popover->widget))
|
||||
{
|
||||
rect->x = 0;
|
||||
rect->width = win_alloc.width;
|
||||
}
|
||||
else
|
||||
rect->x = CLAMP (popover->rect.x + (popover->rect.width / 2) -
|
||||
(req.width / 2), 0, win_alloc.width - req.width);
|
||||
|
||||
if (popover->pos == GTK_POS_TOP)
|
||||
{
|
||||
rect->y = popover->rect.y - req.height;
|
||||
|
||||
if (rect->y > 0 && gtk_widget_get_vexpand (popover->widget))
|
||||
{
|
||||
rect->y = 0;
|
||||
rect->height = popover->rect.y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rect->y = popover->rect.y + popover->rect.height;
|
||||
|
||||
if (rect->y + rect->height < win_alloc.height &&
|
||||
gtk_widget_get_vexpand (popover->widget))
|
||||
rect->height = win_alloc.height - rect->y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
popover_realize (GtkWidget *widget,
|
||||
GtkWindowPopover *popover,
|
||||
GtkWindow *window)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
GdkWindow *parent_window;
|
||||
GdkWindowAttr attributes;
|
||||
gint attributes_mask;
|
||||
|
||||
if (popover->window)
|
||||
return;
|
||||
|
||||
popover_get_rect (popover, window, &rect);
|
||||
|
||||
attributes.window_type = GDK_WINDOW_CHILD;
|
||||
attributes.wclass = GDK_INPUT_OUTPUT;
|
||||
attributes.x = rect.x;
|
||||
attributes.y = rect.y;
|
||||
attributes.width = rect.width;
|
||||
attributes.height = rect.height;
|
||||
attributes.visual = gtk_widget_get_visual (widget);
|
||||
attributes.event_mask = gtk_widget_get_events (popover->widget) |
|
||||
GDK_EXPOSURE_MASK;
|
||||
attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
|
||||
|
||||
parent_window = gtk_widget_get_window (GTK_WIDGET (window));
|
||||
popover->window =
|
||||
gdk_window_new (parent_window, &attributes, attributes_mask);
|
||||
gtk_widget_register_window (GTK_WIDGET (window), popover->window);
|
||||
|
||||
gtk_widget_set_parent_window (popover->widget, popover->window);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_realize (GtkWidget *widget)
|
||||
{
|
||||
@ -5688,6 +5895,7 @@ gtk_window_realize (GtkWidget *widget)
|
||||
GtkWindowPrivate *priv;
|
||||
gint i;
|
||||
int old_scale;
|
||||
GList *link;
|
||||
|
||||
window = GTK_WINDOW (widget);
|
||||
priv = window->priv;
|
||||
@ -5926,18 +6134,37 @@ gtk_window_realize (GtkWidget *widget)
|
||||
if (priv->has_resize_grip)
|
||||
resize_grip_create_window (window);
|
||||
|
||||
link = priv->popovers;
|
||||
|
||||
while (link)
|
||||
{
|
||||
GtkWindowPopover *popover = link->data;
|
||||
link = link->next;
|
||||
popover_realize (popover->widget, popover, window);
|
||||
}
|
||||
|
||||
old_scale = priv->scale;
|
||||
priv->scale = gtk_widget_get_scale_factor (widget);
|
||||
if (old_scale != priv->scale)
|
||||
_gtk_widget_scale_changed (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
popover_unrealize (GtkWidget *widget,
|
||||
GtkWindowPopover *popover)
|
||||
{
|
||||
gtk_widget_unrealize (popover->widget);
|
||||
gdk_window_destroy (popover->window);
|
||||
popover->window = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_unrealize (GtkWidget *widget)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (widget);
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
GtkWindowGeometryInfo *info;
|
||||
GList *link;
|
||||
gint i;
|
||||
|
||||
/* On unrealize, we reset the size of the window such
|
||||
@ -5982,6 +6209,15 @@ gtk_window_unrealize (GtkWidget *widget)
|
||||
}
|
||||
}
|
||||
|
||||
link = priv->popovers;
|
||||
|
||||
while (link)
|
||||
{
|
||||
GtkWindowPopover *popover = link->data;
|
||||
link = link->next;
|
||||
popover_unrealize (popover->widget, popover);
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget);
|
||||
}
|
||||
|
||||
@ -6697,19 +6933,56 @@ _gtk_window_set_allocation (GtkWindow *window,
|
||||
*allocation_out = child_allocation;
|
||||
}
|
||||
|
||||
static void
|
||||
popover_size_allocate (GtkWidget *widget,
|
||||
GtkWindowPopover *popover,
|
||||
GtkWindow *window)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
if (!popover->window)
|
||||
return;
|
||||
|
||||
popover_get_rect (popover, window, &rect);
|
||||
gdk_window_move_resize (popover->window, rect.x, rect.y,
|
||||
rect.width, rect.height);
|
||||
rect.x = rect.y = 0;
|
||||
gtk_widget_size_allocate (widget, &rect);
|
||||
|
||||
if (gtk_widget_is_drawable (GTK_WIDGET (window)) &&
|
||||
gtk_widget_is_visible (widget))
|
||||
{
|
||||
if (!gdk_window_is_visible (popover->window))
|
||||
gdk_window_show (popover->window);
|
||||
}
|
||||
else if (gdk_window_is_visible (popover->window))
|
||||
gdk_window_hide (popover->window);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (widget);
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
GtkWidget *child;
|
||||
GtkAllocation child_allocation;
|
||||
GList *link;
|
||||
|
||||
_gtk_window_set_allocation (window, allocation, &child_allocation);
|
||||
|
||||
child = gtk_bin_get_child (GTK_BIN (window));
|
||||
if (child && gtk_widget_get_visible (child))
|
||||
gtk_widget_size_allocate (child, &child_allocation);
|
||||
|
||||
link = priv->popovers;
|
||||
|
||||
while (link)
|
||||
{
|
||||
GtkWindowPopover *popover = link->data;
|
||||
link = link->next;
|
||||
popover_size_allocate (popover->widget, popover, window);
|
||||
}
|
||||
}
|
||||
|
||||
static gint
|
||||
@ -7479,6 +7752,27 @@ gtk_window_button_press_event (GtkWidget *widget,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gtk_window_check_handle_wm_event (GdkEvent *event)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = gtk_get_event_widget (event);
|
||||
|
||||
if (!GTK_IS_WINDOW (widget))
|
||||
return FALSE;
|
||||
|
||||
if (event->type == GDK_BUTTON_PRESS ||
|
||||
event->type == GDK_2BUTTON_PRESS)
|
||||
return gtk_window_button_press_event (widget, &event->button);
|
||||
else if (event->type == GDK_BUTTON_RELEASE)
|
||||
gtk_window_button_release_event (widget, &event->button);
|
||||
else if (event->type == GDK_MOTION_NOTIFY)
|
||||
return gtk_window_motion_notify_event (widget, &event->motion);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_real_activate_default (GtkWindow *window)
|
||||
{
|
||||
@ -7614,13 +7908,34 @@ gtk_window_focus_out_event (GtkWidget *widget,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GtkWindowPopover *
|
||||
_gtk_window_has_popover (GtkWindow *window,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkWindowPrivate *priv = window->priv;
|
||||
GList *link;
|
||||
|
||||
for (link = priv->popovers; link; link = link->next)
|
||||
{
|
||||
GtkWindowPopover *popover = link->data;
|
||||
|
||||
if (popover->widget == widget)
|
||||
return popover;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_remove (GtkContainer *container,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkWindow *window = GTK_WINDOW (container);
|
||||
|
||||
if (widget == window->priv->title_box)
|
||||
unset_titlebar (window);
|
||||
else if (_gtk_window_has_popover (window, widget))
|
||||
_gtk_window_remove_popover (window, widget);
|
||||
else
|
||||
GTK_CONTAINER_CLASS (gtk_window_parent_class)->remove (container, widget);
|
||||
}
|
||||
@ -9395,11 +9710,13 @@ gtk_window_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv;
|
||||
GtkWindowPopover *popover;
|
||||
GtkStyleContext *context;
|
||||
gboolean ret = FALSE;
|
||||
GtkAllocation allocation;
|
||||
GtkBorder window_border;
|
||||
gint title_height;
|
||||
GList *link;
|
||||
|
||||
context = gtk_widget_get_style_context (widget);
|
||||
|
||||
@ -9483,6 +9800,19 @@ gtk_window_draw (GtkWidget *widget,
|
||||
gtk_style_context_restore (context);
|
||||
}
|
||||
|
||||
link = priv->popovers;
|
||||
|
||||
while (link)
|
||||
{
|
||||
popover = link->data;
|
||||
link = link->next;
|
||||
|
||||
if (popover->window && gtk_widget_is_visible (popover->widget) &&
|
||||
gtk_cairo_should_draw_window (cr, popover->window))
|
||||
gtk_container_propagate_draw (GTK_CONTAINER (widget),
|
||||
popover->widget, cr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -11697,3 +12027,122 @@ _gtk_window_get_shadow_width (GtkWindow *window,
|
||||
{
|
||||
get_shadow_width (GTK_WIDGET (window), border);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_window_add_popover (GtkWindow *window,
|
||||
GtkWidget *popover)
|
||||
{
|
||||
GtkWindowPrivate *priv;
|
||||
GtkWindowPopover *data;
|
||||
|
||||
g_return_if_fail (GTK_IS_WINDOW (window));
|
||||
g_return_if_fail (GTK_IS_WIDGET (popover));
|
||||
g_return_if_fail (gtk_widget_get_parent (popover) == NULL);
|
||||
|
||||
priv = window->priv;
|
||||
|
||||
if (_gtk_window_has_popover (window, popover))
|
||||
return;
|
||||
|
||||
data = g_new0 (GtkWindowPopover, 1);
|
||||
data->widget = popover;
|
||||
priv->popovers = g_list_prepend (priv->popovers, data);
|
||||
|
||||
if (gtk_widget_get_realized (GTK_WIDGET (window)))
|
||||
popover_realize (popover, data, window);
|
||||
|
||||
gtk_widget_set_parent (popover, GTK_WIDGET (window));
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_window_remove_popover (GtkWindow *window,
|
||||
GtkWidget *popover)
|
||||
{
|
||||
GtkWindowPrivate *priv;
|
||||
GtkWindowPopover *data;
|
||||
|
||||
g_return_if_fail (GTK_IS_WINDOW (window));
|
||||
g_return_if_fail (GTK_IS_WIDGET (popover));
|
||||
|
||||
priv = window->priv;
|
||||
|
||||
data = _gtk_window_has_popover (window, popover);
|
||||
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
priv->popovers = g_list_remove (priv->popovers, data);
|
||||
popover_destroy (data);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_window_set_popover_position (GtkWindow *window,
|
||||
GtkWidget *popover,
|
||||
GtkPositionType pos,
|
||||
const cairo_rectangle_int_t *rect)
|
||||
{
|
||||
GtkWindowPopover *data;
|
||||
|
||||
g_return_if_fail (GTK_IS_WINDOW (window));
|
||||
g_return_if_fail (GTK_IS_WIDGET (popover));
|
||||
|
||||
data = _gtk_window_has_popover (window, popover);
|
||||
|
||||
if (!data)
|
||||
{
|
||||
g_warning ("Widget %s(%p) is not a popover of window %s",
|
||||
gtk_widget_get_name (popover), popover,
|
||||
gtk_widget_get_name (GTK_WIDGET (window)));
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (data->pos == pos &&
|
||||
memcmp (&data->rect, rect, sizeof (cairo_rectangle_int_t)) == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
data->rect = *rect;
|
||||
data->pos = pos;
|
||||
|
||||
if (gtk_widget_is_visible (popover))
|
||||
{
|
||||
if (!data->window)
|
||||
{
|
||||
popover_realize (popover, data, window);
|
||||
popover_map (popover, data);
|
||||
}
|
||||
else
|
||||
gdk_window_raise (data->window);
|
||||
}
|
||||
|
||||
gtk_widget_queue_resize (popover);
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_window_get_popover_position (GtkWindow *window,
|
||||
GtkWidget *popover,
|
||||
GtkPositionType *pos,
|
||||
cairo_rectangle_int_t *rect)
|
||||
{
|
||||
GtkWindowPopover *data;
|
||||
|
||||
g_return_if_fail (GTK_IS_WINDOW (window));
|
||||
g_return_if_fail (GTK_IS_WIDGET (popover));
|
||||
|
||||
data = _gtk_window_has_popover (window, popover);
|
||||
|
||||
if (!data)
|
||||
{
|
||||
g_warning ("Widget %s(%p) is not a popover of window %s",
|
||||
gtk_widget_get_name (popover), popover,
|
||||
gtk_widget_get_name (GTK_WIDGET (window)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (pos)
|
||||
*pos = data->pos;
|
||||
|
||||
if (rect)
|
||||
*rect = data->rect;
|
||||
}
|
||||
|
@ -75,6 +75,8 @@ void _gtk_window_keys_foreach (GtkWindow *window,
|
||||
GtkWindowKeysForeachFunc func,
|
||||
gpointer func_data);
|
||||
|
||||
gboolean _gtk_window_check_handle_wm_event (GdkEvent *event);
|
||||
|
||||
/* --- internal (GtkAcceleratable) --- */
|
||||
gboolean _gtk_window_query_nonaccels (GtkWindow *window,
|
||||
guint accel_key,
|
||||
@ -91,6 +93,20 @@ void _gtk_window_get_shadow_width (GtkWindow *window,
|
||||
|
||||
void _gtk_window_toggle_maximized (GtkWindow *window);
|
||||
|
||||
/* Popovers */
|
||||
void _gtk_window_add_popover (GtkWindow *window,
|
||||
GtkWidget *popover);
|
||||
void _gtk_window_remove_popover (GtkWindow *window,
|
||||
GtkWidget *popover);
|
||||
void _gtk_window_set_popover_position (GtkWindow *window,
|
||||
GtkWidget *popover,
|
||||
GtkPositionType pos,
|
||||
const cairo_rectangle_int_t *rect);
|
||||
void _gtk_window_get_popover_position (GtkWindow *window,
|
||||
GtkWidget *popover,
|
||||
GtkPositionType *pos,
|
||||
cairo_rectangle_int_t *rect);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_WINDOW_PRIVATE_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user