Merge branch 'gtk-4-10-backports' into 'gtk-4-10'

tests: Stop copying the tool tests

See merge request GNOME/gtk!6062
This commit is contained in:
Matthias Clasen 2023-06-05 12:35:40 +00:00
commit b77a5fedd2
54 changed files with 590 additions and 404 deletions

View File

@ -1309,6 +1309,13 @@ node_editor_window_init (NodeEditorWindow *self)
" }\n"
" transform: translate(0, 140);\n"
"}", -1);
if (g_getenv ("GSK_RENDERER"))
{
char *new_title = g_strdup_printf ("GTK Node Editor - %s", g_getenv ("GSK_RENDERER"));
gtk_window_set_title (GTK_WINDOW (self), new_title);
g_free (new_title);
}
}
NodeEditorWindow *

View File

@ -220,6 +220,6 @@ clipboard.cut, clipboard.copy, clipboard.paste
selection.delete, selection.select-all
: Selection operations on entries, text view and labels
color.select, color.customize:
color.select, color.customize
: Operate on colors in a `GtkColorChooserWidget`. These actions are
unusual in that they have the non-trivial parameter type (dddd):
unusual in that they have the non-trivial parameter type (dddd).

View File

@ -68,7 +68,7 @@ in a selector, widget names must be prefixed with a # character.
| E:focus-within | [CSS Selector Level 4](https://drafts.csswg.org/selectors/#focus-within-pseudo) | Set on all ancestors of the focus widget, unlike CSS |
| E:focus-visible | [CSS Selector Level 4](https://drafts.csswg.org/selectors/#focus-within-pseudo) | Set on focus widget and all ancestors, unlike CSS |
| E:disabled | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#UIstates) | Corresponds to GTK_STATE_FLAG_INSENSITIVE |
| E:disabled | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#UIstates) | Corresponds to GTK_STATE_FLAG_CHECKED |
| E:checked | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#UIstates) | Corresponds to GTK_STATE_FLAG_CHECKED |
| E:indeterminate | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#indeterminate) | Corresponds to GTK_STATE_FLAG_INCONSISTENT |
| E:backdrop, E:selected | | Corresponds to GTK_STATE_FLAG_BACKDROP, GTK_STATE_FLAG_SELECTED |
| E:not(selector) | [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/#negation) | |

View File

@ -103,14 +103,15 @@ fields, but e.g. buttons can take the focus too.
Input widgets can be given the focus by clicking on them, but focus
can also be moved around with certain key events (this is known as
“keyboard navigation”). GTK reserves the <kbd>Tab</kbd> key to move the focus
to the next location, and <kbd>Shift</kbd>+<kbd>Tab</kbd> to move it back to the previous
one. In addition many containers allow “directional navigation” with
the arrow keys.
“keyboard navigation”).
GTK reserves the <kbd>Tab</kbd> key to move the focus to the next location,
and <kbd>Shift</kbd>+<kbd>Tab</kbd> to move it back to the previous one.
In addition many containers allow “directional navigation” with the arrow keys.
Many widgets can be “activated” to trigger and action. E.g., you can
activate a button or switch by clicking on them, but you can also
activate them with the keyboard, by using the <kbd>Enter</kbd> or <kbd></kbd> keys.
Many widgets can be “activated” to trigger and action.
E.g., you can activate a button or switch by clicking on them,
but you can also activate them with the keyboard,
by using the <kbd>Enter</kbd> or <kbd>Space</kbd> keys.
Apart from keyboard navigation, activation and directly typing into
entries or text views, GTK widgets can use key events for activating
@ -121,15 +122,17 @@ GTK has traditionally supported different kinds of shortcuts:
- Accelerators are any other shortcuts that can be activated regardless
of where the focus is, and typically trigger global actions, such as
Ctrl-Q to quit an application.
- Mnemonics are usually triggered using Alt as a modifier for a letter.
<kbd>Ctrl</kbd>+<kbd>Q</kbd> to quit an application.
- Mnemonics are usually triggered using <kbd>Alt</kbd>
as a modifier for a letter.
They are used in places where a label is associated with a control,
and are indicated by underlining the letter in the label. As a special
case, inside menus (i.e. inside `GtkPopoverMenu`), mnemonics can be
triggered without the modifier.
- Key bindings are specific to individual widgets, such as Ctrl-C or
Ctrl-V in an entry copy to or paste from the clipboard. They are only
triggered when the widget has focus.
- Key bindings are specific to individual widgets,
such as <kbd>Ctrl</kbd>+<kbd>C</kbd> or <kbd>Ctrl</kbd>+<kbd>V</kbd>
in an entry copy to or paste from the clipboard.
They are only triggered when the widget has focus.
GTK handles accelerators and mnemonics in a global scope, during the
capture phase, and key bindings locally, during the target phase.
@ -208,4 +211,4 @@ sequence, so setting the state on one does transfer the state to
the others. They also are mutually exclusive, within a widget
where may be only one gesture group claiming a given sequence.
If another gesture group claims later that same sequence, the
first group will deny the sequence:
first group will deny the sequence.

7
examples/hello/README.md Normal file
View File

@ -0,0 +1,7 @@
A trivial example
=================
This is a very minimal example of an app that can be built against GTK.
We use this in CI to test that building against the installed GTK works.
That is why there is a standalone meson.build in this subdirectory.

View File

@ -371,6 +371,12 @@ gdk_draw_context_begin_frame_full (GdkDrawContext *context,
priv->surface->paint_context = g_object_ref (context);
GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context, prefers_high_depth, priv->frame_region);
cairo_region_intersect_rectangle (priv->frame_region,
&(cairo_rectangle_int_t) {
0, 0,
priv->surface->width, priv->surface->height
});
}
#ifdef HAVE_SYSPROF

View File

@ -165,7 +165,7 @@ parse_rgb_value (const char *str,
*
* The string can be either one of:
*
* - A standard name (Taken from the Css specification).
* - A standard name (Taken from the CSS specification).
* - A hexadecimal value in the form \#rgb, \#rrggbb,
* \#rrrgggbbb or \#rrrrggggbbbb
* - A hexadecimal value in the form \#rgba, \#rrggbbaa,
@ -173,6 +173,8 @@ parse_rgb_value (const char *str,
* - A RGB color in the form rgb(r,g,b) (In this case the color
* will have full opacity)
* - A RGBA color in the form rgba(r,g,b,a)
* - A HSL color in the form "hsl(hue, saturation, lightness)"
* - A HSLA color in the form "hsla(hue, saturation, lightness, alpha)"
*
* Where r, g, b and a are respectively the red, green,
* blue and alpha color values. In the last two cases, r, g,

View File

@ -207,7 +207,7 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
{
char *path;
XcursorImages *images;
struct cursor *cursor;
struct wl_cursor *cursor;
struct cursor_image *image;
int i, nbytes;
unsigned int load_size;
@ -240,17 +240,16 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
return NULL;
}
cursor->cursor.images =
malloc(images->nimage * sizeof cursor->cursor.images[0]);
if (!cursor->cursor.images) {
cursor->images =
malloc(images->nimage * sizeof cursor->images[0]);
if (!cursor->images) {
free(cursor);
xcursor_images_destroy (images);
return NULL;
}
cursor->cursor.name = strdup(name);
cursor->cursor.size = load_size;
cursor->total_delay = 0;
cursor->name = strdup(name);
cursor->size = load_size;
for (i = 0; i < images->nimage; i++) {
image = malloc(sizeof *image);
@ -291,14 +290,13 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
}
}
}
cursor->total_delay += image->image.delay;
cursor->cursor.images[i] = (struct wl_cursor_image *) image;
cursor->images[i] = (struct wl_cursor_image *) image;
}
cursor->cursor.image_count = i;
cursor->image_count = i;
if (cursor->cursor.image_count == 0) {
free(cursor->cursor.name);
free(cursor->cursor.images);
if (cursor->image_count == 0) {
free(cursor->name);
free(cursor->images);
free(cursor);
xcursor_images_destroy (images);
return NULL;
@ -306,7 +304,7 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
xcursor_images_destroy (images);
return &cursor->cursor;
return cursor;
}
static void

View File

@ -443,9 +443,6 @@ populate_monitor_devices_from_display_config (GPtrArray *monitors)
char *path, *path_lower;
DISPLAYCONFIG_RATIONAL *refresh;
if ((dispconf_paths[path_index].flags & DISPLAYCONFIG_PATH_ACTIVE) == 0)
continue;
tdn.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
tdn.header.size = sizeof (tdn);
tdn.header.adapterId = dispconf_paths[path_index].targetInfo.adapterId;
@ -481,6 +478,12 @@ populate_monitor_devices_from_display_config (GPtrArray *monitors)
if (w32mon == NULL)
continue;
if ((dispconf_paths[path_index].flags & DISPLAYCONFIG_PATH_ACTIVE) == 0)
{
w32mon->remove = TRUE;
continue;
}
mon = GDK_MONITOR (w32mon);
if (!tdn.flags.friendlyNameForced)

View File

@ -145,7 +145,8 @@ struct _GdkX11Display
guint server_time_is_monotonic_time : 1;
/* GLX extensions we check */
guint has_glx_swap_interval : 1;
guint has_glx_sgi_swap_control : 1;
guint has_glx_swap_control : 1;
guint has_glx_create_context : 1;
guint has_glx_texture_from_pixmap : 1;
guint has_glx_video_sync : 1;

View File

@ -134,35 +134,6 @@ struct _GdkX11DragClass
GdkDragClass parent_class;
};
typedef struct {
int keysym;
int modifiers;
} GrabKey;
static GrabKey grab_keys[] = {
{ XK_Escape, 0 },
{ XK_space, 0 },
{ XK_KP_Space, 0 },
{ XK_Return, 0 },
{ XK_KP_Enter, 0 },
{ XK_Up, 0 },
{ XK_Up, Mod1Mask },
{ XK_Down, 0 },
{ XK_Down, Mod1Mask },
{ XK_Left, 0 },
{ XK_Left, Mod1Mask },
{ XK_Right, 0 },
{ XK_Right, Mod1Mask },
{ XK_KP_Up, 0 },
{ XK_KP_Up, Mod1Mask },
{ XK_KP_Down, 0 },
{ XK_KP_Down, Mod1Mask },
{ XK_KP_Left, 0 },
{ XK_KP_Left, Mod1Mask },
{ XK_KP_Right, 0 },
{ XK_KP_Right, Mod1Mask }
};
/* Forward declarations */
static GdkSurfaceCache *gdk_surface_cache_ref (GdkSurfaceCache *cache);
@ -1899,20 +1870,15 @@ drag_grab (GdkDrag *drag)
{
GdkX11Drag *x11_drag = GDK_X11_DRAG (drag);
GdkSeatCapabilities capabilities;
GdkDisplay *display;
Window root;
GdkSeat *seat;
int keycode, i;
GdkCursor *cursor;
if (!x11_drag->ipc_surface)
return FALSE;
display = gdk_drag_get_display (drag);
root = GDK_DISPLAY_XROOTWIN (display);
seat = gdk_device_get_seat (gdk_drag_get_device (drag));
capabilities = GDK_SEAT_CAPABILITY_ALL_POINTING | GDK_SEAT_CAPABILITY_KEYBOARD;
capabilities = GDK_SEAT_CAPABILITY_ALL_POINTING;
cursor = gdk_drag_get_cursor (drag, x11_drag->current_action);
g_set_object (&x11_drag->cursor, cursor);
@ -1924,46 +1890,6 @@ drag_grab (GdkDrag *drag)
g_set_object (&x11_drag->grab_seat, seat);
gdk_x11_display_error_trap_push (display);
for (i = 0; i < G_N_ELEMENTS (grab_keys); ++i)
{
int deviceid = gdk_x11_device_get_id (gdk_seat_get_keyboard (seat));
unsigned char mask[XIMaskLen(XI_LASTEVENT)];
XIGrabModifiers mods;
XIEventMask evmask;
int num_mods;
keycode = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (display),
grab_keys[i].keysym);
if (keycode == NoSymbol)
continue;
memset (mask, 0, sizeof (mask));
XISetMask (mask, XI_KeyPress);
XISetMask (mask, XI_KeyRelease);
evmask.deviceid = deviceid;
evmask.mask_len = sizeof (mask);
evmask.mask = mask;
num_mods = 1;
mods.modifiers = grab_keys[i].modifiers;
XIGrabKeycode (GDK_DISPLAY_XDISPLAY (display),
deviceid,
keycode,
root,
GrabModeAsync,
GrabModeAsync,
False,
&evmask,
num_mods,
&mods);
}
gdk_x11_display_error_trap_pop_ignored (display);
return TRUE;
}
@ -1971,41 +1897,13 @@ static void
drag_ungrab (GdkDrag *drag)
{
GdkX11Drag *x11_drag = GDK_X11_DRAG (drag);
GdkDisplay *display;
GdkDevice *keyboard;
Window root;
int keycode, i;
if (!x11_drag->grab_seat)
return;
gdk_seat_ungrab (x11_drag->grab_seat);
display = gdk_drag_get_display (drag);
keyboard = gdk_seat_get_keyboard (x11_drag->grab_seat);
root = GDK_DISPLAY_XROOTWIN (display);
g_clear_object (&x11_drag->grab_seat);
for (i = 0; i < G_N_ELEMENTS (grab_keys); ++i)
{
XIGrabModifiers mods;
int num_mods;
keycode = XKeysymToKeycode (GDK_DISPLAY_XDISPLAY (display),
grab_keys[i].keysym);
if (keycode == NoSymbol)
continue;
num_mods = 1;
mods.modifiers = grab_keys[i].modifiers;
XIUngrabKeycode (GDK_DISPLAY_XDISPLAY (display),
gdk_x11_device_get_id (keyboard),
keycode,
root,
num_mods,
&mods);
}
}
GdkDrag *
@ -2232,103 +2130,6 @@ gdk_dnd_handle_motion_event (GdkDrag *drag,
return TRUE;
}
static gboolean
gdk_dnd_handle_key_event (GdkDrag *drag,
GdkEvent *event)
{
GdkX11Drag *x11_drag = GDK_X11_DRAG (drag);
GdkModifierType state;
GdkDevice *pointer;
GdkSeat *seat;
int dx, dy;
dx = dy = 0;
state = gdk_event_get_modifier_state (event);
seat = gdk_event_get_seat (event);
pointer = gdk_seat_get_pointer (seat);
if (event->event_type == GDK_KEY_PRESS)
{
guint keyval = gdk_key_event_get_keyval (event);
switch (keyval)
{
case GDK_KEY_Escape:
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_USER_CANCELLED);
return TRUE;
case GDK_KEY_space:
case GDK_KEY_Return:
case GDK_KEY_ISO_Enter:
case GDK_KEY_KP_Enter:
case GDK_KEY_KP_Space:
if ((gdk_drag_get_selected_action (drag) != 0) &&
(x11_drag->proxy_xid != None))
{
g_signal_emit_by_name (drag, "drop-performed");
}
else
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
return TRUE;
case GDK_KEY_Up:
case GDK_KEY_KP_Up:
dy = (state & GDK_ALT_MASK) ? -BIG_STEP : -SMALL_STEP;
break;
case GDK_KEY_Down:
case GDK_KEY_KP_Down:
dy = (state & GDK_ALT_MASK) ? BIG_STEP : SMALL_STEP;
break;
case GDK_KEY_Left:
case GDK_KEY_KP_Left:
dx = (state & GDK_ALT_MASK) ? -BIG_STEP : -SMALL_STEP;
break;
case GDK_KEY_Right:
case GDK_KEY_KP_Right:
dx = (state & GDK_ALT_MASK) ? BIG_STEP : SMALL_STEP;
break;
default:
break;
}
}
/* The state is not yet updated in the event, so we need
* to query it here. We could use XGetModifierMapping, but
* that would be overkill.
*/
gdk_x11_device_xi2_query_state (pointer, NULL, NULL, NULL, &state);
if (dx != 0 || dy != 0)
{
GdkDisplay *display;
Display *xdisplay;
GdkX11Screen *screen;
Window dest;
x11_drag->last_x += dx;
x11_drag->last_y += dy;
display = gdk_event_get_display ((GdkEvent *)event);
xdisplay = GDK_DISPLAY_XDISPLAY (display);
screen = GDK_X11_DISPLAY (display)->screen;
dest = GDK_SCREEN_XROOTWIN (screen);
XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0,
round (x11_drag->last_x * screen->surface_scale),
round (x11_drag->last_y * screen->surface_scale));
}
gdk_drag_update (drag, x11_drag->last_x, x11_drag->last_y, state,
gdk_event_get_time (event));
return TRUE;
}
static gboolean
gdk_dnd_handle_grab_broken_event (GdkDrag *drag,
GdkEvent *event)
@ -2395,10 +2196,6 @@ gdk_x11_drag_handle_event (GdkDrag *drag,
case GDK_BUTTON_RELEASE:
return gdk_dnd_handle_button_event (drag, event);
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
return gdk_dnd_handle_key_event (drag, event);
case GDK_GRAB_BROKEN:
return gdk_dnd_handle_grab_broken_event (drag, event);

View File

@ -162,7 +162,7 @@ gdk_x11_gl_context_glx_end_frame (GdkDrawContext *draw_context,
if (display_x11->has_glx_video_sync)
glXGetVideoSyncSGI (&end_frame_counter);
if (self->do_frame_sync && !display_x11->has_glx_swap_interval)
if (self->do_frame_sync && !display_x11->has_glx_sgi_swap_control && !display_x11->has_glx_swap_control)
{
glFinish ();
@ -249,7 +249,7 @@ gdk_x11_gl_context_glx_make_current (GdkGLContext *context,
if (!glXMakeContextCurrent (dpy, drawable, drawable, self->glx_context))
return FALSE;
if (!surfaceless && GDK_X11_DISPLAY (display)->has_glx_swap_interval)
if (!surfaceless)
{
/* If the WM is compositing there is no particular need to delay
* the swap when drawing on the offscreen, rendering to the screen
@ -257,14 +257,35 @@ gdk_x11_gl_context_glx_make_current (GdkGLContext *context,
* to the vblank. */
do_frame_sync = ! gdk_display_is_composited (display);
if (do_frame_sync != self->do_frame_sync)
if (GDK_X11_DISPLAY (display)->has_glx_swap_control)
{
self->do_frame_sync = do_frame_sync;
if (do_frame_sync != self->do_frame_sync)
{
self->do_frame_sync = do_frame_sync;
if (do_frame_sync)
glXSwapIntervalSGI (1);
else
glXSwapIntervalSGI (0);
if (do_frame_sync)
glXSwapIntervalEXT (dpy, drawable, 1);
else
glXSwapIntervalEXT (dpy, drawable, 0);
}
}
else if (GDK_X11_DISPLAY (display)->has_glx_sgi_swap_control)
{
/* If the WM is compositing there is no particular need to delay
* the swap when drawing on the offscreen, rendering to the screen
* happens later anyway, and its up to the compositor to sync that
* to the vblank. */
do_frame_sync = ! gdk_display_is_composited (display);
if (do_frame_sync != self->do_frame_sync)
{
self->do_frame_sync = do_frame_sync;
if (do_frame_sync)
glXSwapIntervalSGI (1);
else
glXSwapIntervalSGI (0);
}
}
}
@ -925,8 +946,10 @@ gdk_x11_display_init_glx (GdkX11Display *display_x11,
epoxy_has_glx_extension (dpy, screen_num, "GLX_ARB_create_context_profile");
display_x11->has_glx_create_es2_context =
epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_create_context_es2_profile");
display_x11->has_glx_swap_interval =
display_x11->has_glx_sgi_swap_control =
epoxy_has_glx_extension (dpy, screen_num, "GLX_SGI_swap_control");
display_x11->has_glx_swap_control =
epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_swap_control");
display_x11->has_glx_texture_from_pixmap =
epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_texture_from_pixmap");
display_x11->has_glx_video_sync =
@ -987,6 +1010,7 @@ gdk_x11_display_init_glx (GdkX11Display *display_x11,
"\t* GLX_ARB_create_context_profile: %s\n"
"\t* GLX_EXT_create_context_es2_profile: %s\n"
"\t* GLX_SGI_swap_control: %s\n"
"\t* GLX_EXT_swap_control: %s\n"
"\t* GLX_EXT_texture_from_pixmap: %s\n"
"\t* GLX_SGI_video_sync: %s\n"
"\t* GLX_EXT_buffer_age: %s\n"
@ -998,7 +1022,8 @@ gdk_x11_display_init_glx (GdkX11Display *display_x11,
glXGetClientString (dpy, GLX_VENDOR),
display_x11->has_glx_create_context ? "yes" : "no",
display_x11->has_glx_create_es2_context ? "yes" : "no",
display_x11->has_glx_swap_interval ? "yes" : "no",
display_x11->has_glx_sgi_swap_control ? "yes" : "no",
display_x11->has_glx_swap_control ? "yes" : "no",
display_x11->has_glx_texture_from_pixmap ? "yes" : "no",
display_x11->has_glx_video_sync ? "yes" : "no",
display_x11->has_glx_buffer_age ? "yes" : "no",

View File

@ -685,8 +685,13 @@ init_randr13 (GdkX11Screen *x11_screen)
for (i = 0; i < resources->noutput; ++i)
{
RROutput output = resources->outputs[i];
XRROutputInfo *output_info =
XRRGetOutputInfo (x11_screen->xdisplay, resources, output);
XRROutputInfo *output_info;
gdk_x11_display_error_trap_push (display);
output_info = XRRGetOutputInfo (x11_screen->xdisplay, resources, output);
if (gdk_x11_display_error_trap_pop (display))
continue;
if (output_info->connection == RR_Disconnected)
{
@ -697,13 +702,22 @@ init_randr13 (GdkX11Screen *x11_screen)
if (output_info->crtc)
{
GdkX11Monitor *monitor;
XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc);
XRRCrtcInfo *crtc;
char *name;
GdkRectangle geometry;
GdkRectangle newgeo;
int j;
int refresh_rate = 0;
gdk_x11_display_error_trap_push (display);
crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc);
if (gdk_x11_display_error_trap_pop (display))
{
XRRFreeOutputInfo (output_info);
continue;
}
for (j = 0; j < resources->nmode; j++)
{
XRRModeInfo *xmode = &resources->modes[j];
@ -775,8 +789,10 @@ init_randr13 (GdkX11Screen *x11_screen)
}
x11_display->primary_monitor = 0;
gdk_x11_display_error_trap_push (display);
primary_output = XRRGetOutputPrimary (x11_screen->xdisplay,
x11_screen->xroot_window);
gdk_x11_display_error_trap_pop_ignored (display);
for (i = 0; i < g_list_model_get_n_items (G_LIST_MODEL (x11_display->monitors)); i++)
{

View File

@ -89,7 +89,7 @@ gdk_x11_selection_input_stream_fill_buffer (GdkX11SelectionInputStream *stream,
if (size == 0)
{
/* EOF marker, put it back */
g_async_queue_push_front_unlocked (priv->chunks, bytes);
g_async_queue_push_front_unlocked (priv->chunks, g_steal_pointer (&bytes));
break;
}
else if (size > count)
@ -107,7 +107,7 @@ gdk_x11_selection_input_stream_fill_buffer (GdkX11SelectionInputStream *stream,
memcpy (buffer, g_bytes_get_data (bytes, NULL), size);
}
g_bytes_unref (bytes);
g_bytes_unref (g_steal_pointer (&bytes));
result += size;
if (buffer)
buffer += size;
@ -165,9 +165,7 @@ gdk_x11_selection_input_stream_complete (GdkX11SelectionInputStream *stream)
GDK_X11_DISPLAY (priv->display)->streams = g_slist_remove (GDK_X11_DISPLAY (priv->display)->streams, stream);
g_signal_handlers_disconnect_by_func (priv->display,
gdk_x11_selection_input_stream_xevent,
stream);
g_object_unref (stream);
g_steal_pointer (&stream));
}
static gssize
@ -416,7 +414,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
"%s:%s: got PropertyNotify erroring out of INCR",
priv->selection, priv->target);
/* error, should we signal one? */
gdk_x11_selection_input_stream_complete (stream);
g_clear_pointer (&stream, gdk_x11_selection_input_stream_complete);
}
else if (g_bytes_get_size (bytes) == 0 || type == None)
{
@ -424,7 +422,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
"%s:%s: got PropertyNotify ending INCR",
priv->selection, priv->target);
g_bytes_unref (bytes);
gdk_x11_selection_input_stream_complete (stream);
g_clear_pointer (&stream, gdk_x11_selection_input_stream_complete);
}
else
{
@ -467,7 +465,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
_("Format %s not supported"), priv->target);
gdk_x11_selection_input_stream_complete (stream);
g_clear_pointer (&stream, gdk_x11_selection_input_stream_complete);
}
else
{
@ -478,7 +476,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
if (bytes == NULL)
{
gdk_x11_selection_input_stream_complete (stream);
g_clear_pointer (&stream, gdk_x11_selection_input_stream_complete);
}
else
{
@ -500,7 +498,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
g_bytes_get_size (bytes));
g_async_queue_push (priv->chunks, bytes);
gdk_x11_selection_input_stream_complete (stream);
g_clear_pointer (&stream, gdk_x11_selection_input_stream_complete);
}
}
@ -541,7 +539,10 @@ gdk_x11_selection_input_stream_new_async (GdkDisplay *display,
priv->property = g_strdup_printf ("GDK_SELECTION_%p", stream);
priv->xproperty = gdk_x11_get_xatom_by_name_for_display (display, priv->property);
g_signal_connect (display, "xevent", G_CALLBACK (gdk_x11_selection_input_stream_xevent), stream);
g_signal_connect_data (display, "xevent",
G_CALLBACK (gdk_x11_selection_input_stream_xevent),
g_steal_pointer (&stream),
(GClosureNotify) g_object_unref, 0);
XConvertSelection (GDK_DISPLAY_XDISPLAY (display),
priv->xselection,
@ -577,7 +578,6 @@ gdk_x11_selection_input_stream_new_finish (GAsyncResult *result,
*type = priv->type;
if (format)
*format = priv->format;
g_object_ref (stream);
}
return G_INPUT_STREAM (stream);

View File

@ -662,6 +662,10 @@ gsk_gl_command_queue_split_draw (GskGLCommandQueue *self)
g_assert (GSK_IS_GL_COMMAND_QUEUE (self));
g_assert (self->batches.len > 0);
if (will_ignore_batch (self))
return;
g_assert (self->in_draw == TRUE);
program = self->program_info;

View File

@ -377,6 +377,8 @@ gsk_renderer_render_texture (GskRenderer *renderer,
gsk_render_node_get_bounds (root, &real_viewport);
viewport = &real_viewport;
}
g_return_val_if_fail (viewport->size.width > 0, NULL);
g_return_val_if_fail (viewport->size.height > 0, NULL);
texture = GSK_RENDERER_GET_CLASS (renderer)->render_texture (renderer, root, viewport);

View File

@ -4108,6 +4108,11 @@ gsk_shadow_node_draw (GskRenderNode *node,
pattern = cairo_pop_group (cr);
cairo_restore (cr);
cairo_save (cr);
/* clip so the blur area stays small */
gsk_cairo_rectangle (cr, &node->bounds);
cairo_clip (cr);
for (i = 0; i < self->n_shadows; i++)
{
GskShadow *shadow = &self->shadows[i];
@ -4129,6 +4134,7 @@ gsk_shadow_node_draw (GskRenderNode *node,
cairo_set_source (cr, pattern);
cairo_paint (cr);
cairo_restore (cr);
cairo_pattern_destroy (pattern);
}

View File

@ -325,6 +325,9 @@ gtk_action_muxer_get_group (GtkActionMuxer *muxer,
{
Group *group;
if (!muxer->groups)
return NULL;
group = g_hash_table_lookup (muxer->groups, group_name);
if (group)
return group->group;
@ -452,7 +455,7 @@ notify_observers_added (GtkActionMuxer *muxer,
gtk_action_observable_register_observer (GTK_ACTION_OBSERVABLE (parent), action_name, GTK_ACTION_OBSERVER (muxer));
if (!action_muxer_query_action (parent, action_name,
if (!action_muxer_query_action (muxer, action_name,
&enabled, &parameter_type,
NULL, NULL, &state,
TRUE))

View File

@ -88,7 +88,7 @@ gtk_css_value_corner_transition (GtkCssValue *start,
static void
gtk_css_value_corner_print (const GtkCssValue *corner,
GString *string)
GString *string)
{
_gtk_css_value_print (corner->x, string);
if (!_gtk_css_value_equal (corner->x, corner->y))
@ -109,16 +109,55 @@ static const GtkCssValueClass GTK_CSS_VALUE_CORNER = {
gtk_css_value_corner_print
};
static GtkCssValue corner_singletons[] = {
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
{ &GTK_CSS_VALUE_CORNER, 1, TRUE, NULL, NULL },
};
static inline void
initialize_corner_singletons (void)
{
static gboolean initialized = FALSE;
if (initialized)
return;
for (unsigned int i = 0; i < G_N_ELEMENTS (corner_singletons); i++)
{
corner_singletons[i].x = gtk_css_dimension_value_new (i, GTK_CSS_PX);
corner_singletons[i].y = gtk_css_value_ref (corner_singletons[i].x);
}
initialized = TRUE;
}
GtkCssValue *
_gtk_css_corner_value_new (GtkCssValue *x,
GtkCssValue *y)
{
GtkCssValue *result;
if (_gtk_css_value_equal (x, y))
if (x == y &&
gtk_css_number_value_get_dimension (x) == GTK_CSS_DIMENSION_LENGTH)
{
_gtk_css_value_unref (y);
return x;
initialize_corner_singletons ();
for (unsigned int i = 0; i < G_N_ELEMENTS (corner_singletons); i++)
{
if (corner_singletons[i].x == x)
{
gtk_css_value_unref (x);
gtk_css_value_unref (y);
return gtk_css_value_ref (&corner_singletons[i]);
}
}
}
result = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_CORNER);
@ -162,9 +201,6 @@ double
_gtk_css_corner_value_get_x (const GtkCssValue *corner,
double one_hundred_percent)
{
if (corner->class != &GTK_CSS_VALUE_CORNER)
return _gtk_css_number_value_get (corner, one_hundred_percent);
g_return_val_if_fail (corner != NULL, 0.0);
g_return_val_if_fail (corner->class == &GTK_CSS_VALUE_CORNER, 0.0);
@ -175,9 +211,6 @@ double
_gtk_css_corner_value_get_y (const GtkCssValue *corner,
double one_hundred_percent)
{
if (corner->class != &GTK_CSS_VALUE_CORNER)
return _gtk_css_number_value_get (corner, one_hundred_percent);
g_return_val_if_fail (corner != NULL, 0.0);
g_return_val_if_fail (corner->class == &GTK_CSS_VALUE_CORNER, 0.0);

View File

@ -75,7 +75,8 @@ gtk_css_value_font_features_equal (const GtkCssValue *value1,
g_hash_table_iter_init (&iter, value1->features);
while (g_hash_table_iter_next (&iter, &name, &val1))
{
val2 = g_hash_table_lookup (value2->features, name);
if (!g_hash_table_lookup_extended (value2->features, name, NULL, &val2))
return FALSE;
if (val1 != val2)
return FALSE;
@ -106,11 +107,10 @@ gtk_css_value_font_features_transition (GtkCssValue *start,
g_hash_table_iter_init (&iter, start->features);
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&start_val))
{
end_val = g_hash_table_lookup (end->features, name);
if (end_val == NULL)
if (!g_hash_table_lookup_extended (end->features, name, NULL, &end_val))
transition = start_val;
else
transition = progress > 0.5 ? start_val : end_val;
transition = progress < 0.5 ? start_val : end_val;
gtk_css_font_features_value_add_feature (result, name, GPOINTER_TO_INT (transition));
}
@ -118,8 +118,7 @@ gtk_css_value_font_features_transition (GtkCssValue *start,
g_hash_table_iter_init (&iter, end->features);
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&end_val))
{
start_val = g_hash_table_lookup (start->features, name);
if (start_val != NULL)
if (g_hash_table_lookup_extended (end->features, name, NULL, &start_val))
continue;
gtk_css_font_features_value_add_feature (result, name, GPOINTER_TO_INT (end_val));

View File

@ -47,21 +47,7 @@ gtk_css_image_url_load_image (GtkCssImageUrl *url,
return url->loaded_image;
}
/* We special case resources here so we can use gdk_texture_new_from_resource. */
if (g_file_has_uri_scheme (url->file, "resource"))
{
char *uri = g_file_get_uri (url->file);
char *resource_path = g_uri_unescape_string (uri + strlen ("resource://"), NULL);
texture = gdk_texture_new_from_resource (resource_path);
g_free (resource_path);
g_free (uri);
}
else
{
texture = gdk_texture_new_from_file (url->file, &local_error);
}
texture = gdk_texture_new_from_file (url->file, &local_error);
if (texture == NULL)
{

View File

@ -380,6 +380,9 @@ gtk_css_dimension_value_new (double value,
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 2 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 3 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 4 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 5 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 6 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 7 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 8 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 16 }} }, /* Icon size default */
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 32 }} },
@ -418,16 +421,18 @@ gtk_css_dimension_value_new (double value,
value == 1 ||
value == 2 ||
value == 3 ||
value == 4)
value == 4 ||
value == 5 ||
value == 6 ||
value == 7 ||
value == 8)
return _gtk_css_value_ref (&px_singletons[(int) value]);
if (value == 8)
return _gtk_css_value_ref (&px_singletons[5]);
if (value == 16)
return _gtk_css_value_ref (&px_singletons[6]);
return _gtk_css_value_ref (&px_singletons[9]);
if (value == 32)
return _gtk_css_value_ref (&px_singletons[7]);
return _gtk_css_value_ref (&px_singletons[10]);
if (value == 64)
return _gtk_css_value_ref (&px_singletons[8]);
return _gtk_css_value_ref (&px_singletons[11]);
break;

View File

@ -336,10 +336,10 @@ gtk_css_shadow_value_new_filter (const GtkCssValue *other)
ShadowValue value;
value.inset = FALSE;
value.hoffset = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
value.voffset = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
value.radius = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
value.spread = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
value.hoffset = _gtk_css_number_value_new (0, GTK_CSS_PX);
value.voffset = _gtk_css_number_value_new (0, GTK_CSS_PX);
value.radius = _gtk_css_number_value_new (0, GTK_CSS_PX);
value.spread = _gtk_css_number_value_new (0, GTK_CSS_PX);
value.color = gtk_css_value_ref (other->shadows[0].color);
return gtk_css_shadow_value_new (&value, 1, TRUE);

View File

@ -142,7 +142,7 @@ gtk_css_transform_init_identity (GtkCssTransform *transform,
case GTK_CSS_TRANSFORM_ROTATE:
transform->rotate.x = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
transform->rotate.y = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
transform->rotate.z = _gtk_css_number_value_new (0, GTK_CSS_NUMBER);
transform->rotate.z = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
transform->rotate.angle = _gtk_css_number_value_new (0, GTK_CSS_DEG);
break;
case GTK_CSS_TRANSFORM_SCALE:

View File

@ -410,16 +410,22 @@ gtk_event_controller_scroll_handle_event (GtkEventController *controller,
}
else
{
if (ABS (scroll->cur_dx) >= 1)
if (ABS (scroll->cur_dx) >= 0.5)
{
steps = trunc (scroll->cur_dx);
if (steps == 0)
steps = (scroll->cur_dx > 0) ? 1 : -1;
scroll->cur_dx -= steps;
dx = steps;
}
if (ABS (scroll->cur_dy) >= 1)
if (ABS (scroll->cur_dy) >= 0.5)
{
steps = trunc (scroll->cur_dy);
if (steps == 0)
steps = (scroll->cur_dy > 0) ? 1 : -1;
scroll->cur_dy -= steps;
dy = steps;
}
@ -459,16 +465,22 @@ gtk_event_controller_scroll_handle_event (GtkEventController *controller,
scroll->cur_dy += dy;
dx = dy = 0;
if (ABS (scroll->cur_dx) >= 1)
if (ABS (scroll->cur_dx) >= 0.5)
{
steps = trunc (scroll->cur_dx);
if (steps == 0)
steps = (scroll->cur_dx > 0) ? 1 : -1;
scroll->cur_dx -= steps;
dx = steps;
}
if (ABS (scroll->cur_dy) >= 1)
if (ABS (scroll->cur_dy) >= 0.5)
{
steps = trunc (scroll->cur_dy);
if (steps == 0)
steps = (scroll->cur_dy > 0) ? 1 : -1;
scroll->cur_dy -= steps;
dy = steps;
}

View File

@ -40,7 +40,7 @@
* expanded widget yourself, such as when you want to actually create
* the widget at expansion time. In this case, create a `GtkExpander`
* but do not add a child to it. The expander widget has an
* [property@Gtk.Expander:expanded[ property which can be used to
* [property@Gtk.Expander:expanded] property which can be used to
* monitor its expansion state. You should watch this property with
* a signal connection as follows:
*

View File

@ -578,7 +578,10 @@ gtk_file_chooser_widget_finalize (GObject *object)
stop_loading_and_clear_list_model (impl, FALSE);
search_clear_model (impl, FALSE);
recent_clear_model (impl, FALSE);
g_clear_object (&impl->recent_model);
g_clear_object (&impl->search_model);
g_clear_object (&impl->model_for_search);
g_clear_object (&impl->browse_files_model);
g_clear_object (&impl->selection_model);
g_clear_object (&impl->sort_model);
@ -3981,6 +3984,7 @@ set_list_model (GtkFileChooserWidget *impl,
set_busy_cursor (impl, TRUE);
g_clear_object (&impl->browse_files_model);
impl->browse_files_model =
_gtk_file_system_model_new_for_directory (impl->current_folder, MODEL_ATTRIBUTES);

View File

@ -229,9 +229,9 @@ open_done (GObject *source,
#endif
static void
show_folder_done (GObject *source,
GAsyncResult *result,
gpointer data)
show_item_done (GObject *source,
GAsyncResult *result,
gpointer data)
{
GDBusConnection *bus = G_DBUS_CONNECTION (source);
GTask *task = G_TASK (data);
@ -261,11 +261,10 @@ show_folder_done (GObject *source,
#define FILE_MANAGER_DBUS_PATH "/org/freedesktop/FileManager1"
static void
show_folder (GtkWindow *parent,
const char *uri,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
show_item (GtkWindow *parent,
const char *uri,
GCancellable *cancellable,
GTask *task)
{
GDBusConnection *bus;
GVariantBuilder uris_builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_STRING_ARRAY);
@ -274,10 +273,10 @@ show_folder (GtkWindow *parent,
if (!bus)
{
g_task_return_new_error (G_TASK (user_data),
g_task_return_new_error (task,
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED,
"Session bus not available");
g_object_unref (G_TASK (user_data));
g_object_unref (task);
return;
}
@ -287,14 +286,14 @@ show_folder (GtkWindow *parent,
FILE_MANAGER_DBUS_NAME,
FILE_MANAGER_DBUS_PATH,
FILE_MANAGER_DBUS_IFACE,
"ShowFolders",
"ShowItems",
g_variant_new ("(ass)", &uris_builder, ""),
NULL, /* ignore returned type */
G_DBUS_CALL_FLAGS_NONE,
-1,
cancellable,
show_folder_done,
user_data);
show_item_done,
task);
}
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
@ -470,7 +469,7 @@ gtk_file_launcher_open_containing_folder (GtkFileLauncher *self,
{
char *uri = g_file_get_uri (self->file);
show_folder (parent, uri, cancellable, show_folder_done, task);
show_item (parent, uri, cancellable, task);
g_free (uri);
}

View File

@ -748,7 +748,9 @@ gtk_file_system_model_monitor_change (GFileMonitor * monitor,
case G_FILE_MONITOR_EVENT_CREATED:
case G_FILE_MONITOR_EVENT_CHANGED:
case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED:
/* We can treat all of these the same way */
if (g_file_equal (file, model->dir))
return;
/* We can treat all children the same way */
g_file_query_info_async (file,
model->attributes,
G_FILE_QUERY_INFO_NONE,

View File

@ -1970,10 +1970,13 @@ gtk_label_activate_link_open (GtkWidget *widget,
GVariant *parameter)
{
GtkLabel *self = GTK_LABEL (widget);
GtkLabelLink *link = self->select_info->context_link;
if (self->select_info)
{
GtkLabelLink *link = self->select_info->context_link;
if (link)
emit_activate_link (self, link);
if (link)
emit_activate_link (self, link);
}
}
static void
@ -1982,17 +1985,18 @@ gtk_label_activate_link_copy (GtkWidget *widget,
GVariant *parameter)
{
GtkLabel *self = GTK_LABEL (widget);
GtkLabelLink *link = self->select_info->context_link;
if (link)
if (self->select_info)
{
GdkClipboard *clipboard;
GtkLabelLink *link = self->select_info->context_link;
clipboard = gtk_widget_get_clipboard (widget);
gdk_clipboard_set_text (clipboard, link->uri);
if (link)
{
GdkClipboard *clipboard;
clipboard = gtk_widget_get_clipboard (widget);
gdk_clipboard_set_text (clipboard, link->uri);
}
}
else
g_print ("no link ?!\n");
}
static void

View File

@ -1073,6 +1073,7 @@ gtk_menu_button_get_icon_name (GtkMenuButton *menu_button)
* gtk_menu_button_set_always_show_arrow: (attributes org.gtk.Method.set_property=always-show-arrow)
* @menu_button: a `GtkMenuButton`
* @always_show_arrow: whether to show a dropdown arrow even when using an icon
* or a custom child
*
* Sets whether to show a dropdown arrow even when using an icon or a custom
* child.
@ -1101,9 +1102,11 @@ gtk_menu_button_set_always_show_arrow (GtkMenuButton *menu_button,
* gtk_menu_button_get_always_show_arrow: (attributes org.gtk.Method.get_property=always-show-arrow)
* @menu_button: a `GtkMenuButton`
*
* Gets whether to show a dropdown arrow even when using an icon.
* Gets whether to show a dropdown arrow even when using an icon or a custom
* child.
*
* Returns: whether to show a dropdown arrow even when using an icon
* Returns: whether to show a dropdown arrow even when using an icon or a custom
* child.
*
* Since: 4.4
*/
@ -1526,7 +1529,7 @@ gtk_menu_button_get_child (GtkMenuButton *menu_button)
* @menu_button: a `GtkMenuButton`
* @active: whether the menu button is active
*
* Sets whether menu button acts is active.
* Sets whether the menu button is active.
*
* Since: 4.10
*/

View File

@ -664,7 +664,7 @@ gtk_menu_section_box_new_section (GtkMenuTrackerItem *item,
gtk_orientable_set_orientation (GTK_ORIENTABLE (box->item_box), GTK_ORIENTATION_HORIZONTAL);
gtk_widget_add_css_class (GTK_WIDGET (box->item_box), "inline-buttons");
spacer = gtk_builtin_icon_new ("none");
spacer = gtk_gizmo_new ("none", NULL, NULL, NULL,NULL, NULL, NULL);
gtk_box_append (GTK_BOX (box->item_box), spacer);
gtk_size_group_add_widget (box->indicators, spacer);

View File

@ -314,6 +314,11 @@ gtk_overlay_class_init (GtkOverlayClass *klass)
klass->get_child_position = gtk_overlay_get_child_position;
/**
* GtkOverlay:child: (attributes org.gtk.Property.get=gtk_overlay_get_child org.gtk.Property.set=gtk_overlay_set_child)
*
* The main child widget.
*/
g_object_class_install_property (object_class,
PROP_CHILD,
g_param_spec_object ("child", NULL, NULL,

View File

@ -129,6 +129,7 @@
#include "gtkroundedboxprivate.h"
#include "gsk/gskroundedrectprivate.h"
#include "gtkcssshadowvalueprivate.h"
#include "gtkcsscornervalueprivate.h"
#include "gdk/gdksurfaceprivate.h"
@ -1193,6 +1194,16 @@ gtk_popover_finalize (GObject *object)
G_OBJECT_CLASS (gtk_popover_parent_class)->finalize (object);
}
static double
get_border_radius (GtkWidget *widget)
{
GtkCssStyle *style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
/* FIXME this is a very crude interpretation of border radius */
return MAX (_gtk_css_corner_value_get_x (style->border->border_top_left_radius, 100),
_gtk_css_corner_value_get_y (style->border->border_top_left_radius, 100));
}
static void
gtk_popover_get_gap_coords (GtkPopover *popover,
int *initial_x_out,
@ -1227,7 +1238,7 @@ gtk_popover_get_gap_coords (GtkPopover *popover,
pos = priv->final_position;
style = gtk_css_node_get_style (gtk_widget_get_css_node (priv->contents_widget));
border_radius = _gtk_css_number_value_get (style->border->border_top_left_radius, 100);
border_radius = round (get_border_radius (widget));
border_top = _gtk_css_number_value_get (style->border->border_top_width, 100);
border_right = _gtk_css_number_value_get (style->border->border_right_width, 100);
border_bottom = _gtk_css_number_value_get (style->border->border_bottom_width, 100);
@ -1424,15 +1435,6 @@ gtk_popover_update_shape (GtkPopover *popover)
gtk_native_update_opaque_region (GTK_NATIVE (popover), priv->contents_widget, TRUE, TRUE, 0);
}
static int
get_border_radius (GtkWidget *widget)
{
GtkCssStyle *style;
style = gtk_css_node_get_style (gtk_widget_get_css_node (widget));
return round (_gtk_css_number_value_get (style->border->border_top_left_radius, 100));
}
static int
get_minimal_size (GtkPopover *popover,
GtkOrientation orientation)
@ -1443,7 +1445,7 @@ get_minimal_size (GtkPopover *popover,
int tail_gap_width = priv->has_arrow ? TAIL_GAP_WIDTH : 0;
int min_width, min_height;
minimal_size = 2 * get_border_radius (GTK_WIDGET (priv->contents_widget));
minimal_size = 2 * round (get_border_radius (GTK_WIDGET (priv->contents_widget)));
pos = priv->position;
if ((orientation == GTK_ORIENTATION_HORIZONTAL && POS_IS_VERTICAL (pos)) ||

View File

@ -329,7 +329,7 @@ gtk_property_lookup_list_model_get_property (GObject *object,
break;
case PROP_PROPERTY:
g_value_set_object (value, self->property);
g_value_set_string (value, self->property);
break;
default:
@ -408,7 +408,7 @@ gtk_property_lookup_list_model_class_init (GtkPropertyLookupListModelClass *klas
*/
properties[PROP_OBJECT] =
g_param_spec_object ("object", NULL, NULL,
G_TYPE_LIST_MODEL,
G_TYPE_OBJECT,
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties);
@ -417,6 +417,7 @@ gtk_property_lookup_list_model_class_init (GtkPropertyLookupListModelClass *klas
static void
gtk_property_lookup_list_model_init (GtkPropertyLookupListModel *self)
{
self->item_type = G_TYPE_OBJECT;
self->items = g_ptr_array_new ();
/* add sentinel */
g_ptr_array_add (self->items, NULL);

View File

@ -1431,6 +1431,7 @@ gtk_recent_manager_clamp_to_age (GtkRecentManager *manager,
}
g_strfreev (uris);
g_date_time_unref (now);
}
static void
@ -2180,13 +2181,16 @@ gtk_recent_info_get_uri_display (GtkRecentInfo *info)
int
gtk_recent_info_get_age (GtkRecentInfo *info)
{
int diff;
GDateTime *now;
g_return_val_if_fail (info != NULL, -1);
now = g_date_time_new_now_utc ();
diff = (int) (g_date_time_difference (now, info->modified) / (double)G_TIME_SPAN_DAY);
return (int) (g_date_time_difference (now, info->modified) / (double)G_TIME_SPAN_DAY);
g_date_time_unref (now);
return diff;
}
/**

View File

@ -1747,8 +1747,38 @@ gtk_scrolled_window_measure (GtkWidget *widget,
if (priv->child && gtk_widget_get_visible (priv->child))
{
int min_child_size, nat_child_size;
int child_for_size = -1;
gtk_widget_measure (priv->child, orientation, -1,
/* We can pass on the requested size if we have a scrollbar policy that prevents scrolling in that direction */
if ((orientation == GTK_ORIENTATION_VERTICAL && priv->hscrollbar_policy == GTK_POLICY_NEVER)
|| (orientation == GTK_ORIENTATION_HORIZONTAL && priv->vscrollbar_policy == GTK_POLICY_NEVER))
{
child_for_size = for_size;
/* If the other scrollbar is always visible and not an overlay scrollbar we must subtract it from the measure */
if (orientation == GTK_ORIENTATION_VERTICAL && !priv->use_indicators && priv->vscrollbar_policy == GTK_POLICY_ALWAYS)
{
int min_scrollbar_width;
gtk_widget_measure (priv->vscrollbar, GTK_ORIENTATION_HORIZONTAL, -1,
&min_scrollbar_width, NULL,
NULL, NULL);
child_for_size = MAX (0, child_for_size - min_scrollbar_width);
}
if (orientation == GTK_ORIENTATION_HORIZONTAL && !priv->use_indicators && priv->hscrollbar_policy == GTK_POLICY_ALWAYS)
{
int min_scrollbar_height;
gtk_widget_measure (priv->hscrollbar, GTK_ORIENTATION_VERTICAL, -1,
&min_scrollbar_height, NULL,
NULL, NULL);
child_for_size = MAX (0, child_for_size - min_scrollbar_height);
}
}
gtk_widget_measure (priv->child, orientation, child_for_size,
&min_child_size, &nat_child_size,
NULL, NULL);

View File

@ -40,7 +40,8 @@
#include "gtkmarshalers.h"
#include "gtkeventcontrollerkey.h"
#include "gtkwidgetprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkcsspositionvalueprivate.h"
/**
* GtkSearchEntry:
@ -124,8 +125,9 @@ struct _GtkSearchEntry
guint search_delay;
GtkWidget *search_icon;
GtkWidget *entry;
GtkWidget *icon;
GtkWidget *clear_icon;
guint delayed_changed_id;
gboolean content_changed;
@ -165,10 +167,9 @@ gtk_search_entry_finalize (GObject *object)
gtk_editable_finish_delegate (GTK_EDITABLE (entry));
gtk_widget_unparent (gtk_widget_get_first_child (GTK_WIDGET (entry)));
g_clear_pointer (&entry->search_icon, gtk_widget_unparent);
g_clear_pointer (&entry->entry, gtk_widget_unparent);
g_clear_pointer (&entry->icon, gtk_widget_unparent);
g_clear_pointer (&entry->clear_icon, gtk_widget_unparent);
if (entry->delayed_changed_id > 0)
g_source_remove (entry->delayed_changed_id);
@ -281,6 +282,134 @@ gtk_search_entry_mnemonic_activate (GtkWidget *widget,
return TRUE;
}
static int
get_spacing (GtkWidget *widget)
{
GtkCssNode *node = gtk_widget_get_css_node (widget);
GtkCssStyle *style = gtk_css_node_get_style (node);
return _gtk_css_position_value_get_x (style->size->border_spacing, 100);
}
static void
gtk_search_entry_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
GtkSearchEntry *entry = GTK_SEARCH_ENTRY (widget);
int icon_min, icon_nat;
int spacing;
spacing = get_spacing (widget);
gtk_widget_measure (entry->entry,
orientation,
for_size,
minimum, natural,
minimum_baseline, natural_baseline);
gtk_widget_measure (entry->search_icon,
GTK_ORIENTATION_HORIZONTAL,
-1,
&icon_min, &icon_nat,
NULL, NULL);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
*minimum += icon_min + spacing;
*natural += icon_nat + spacing;
}
else
{
*minimum = MAX (*minimum, icon_min);
*natural = MAX (*natural, icon_nat);
}
gtk_widget_measure (entry->clear_icon,
GTK_ORIENTATION_HORIZONTAL,
-1,
&icon_min, &icon_nat,
NULL, NULL);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
*minimum += icon_min + spacing;
*natural += icon_nat + spacing;
}
else
{
*minimum = MAX (*minimum, icon_min);
*natural = MAX (*natural, icon_nat);
}
}
static void
gtk_search_entry_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
GtkSearchEntry *entry = GTK_SEARCH_ENTRY (widget);
gboolean is_rtl;
GtkAllocation text_alloc;
GtkAllocation icon_alloc;
int icon_width;
int spacing;
spacing = get_spacing (widget);
is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
text_alloc.x = 0;
text_alloc.y = 0;
text_alloc.width = width;
text_alloc.height = height;
if (gtk_widget_get_valign (widget) != GTK_ALIGN_BASELINE)
baseline = -1;
gtk_widget_measure (entry->search_icon,
GTK_ORIENTATION_HORIZONTAL,
-1,
NULL, &icon_width,
NULL, NULL);
icon_alloc.x = is_rtl ? width - icon_width : 0;
icon_alloc.y = 0;
icon_alloc.width = icon_width;
icon_alloc.height = height;
gtk_widget_size_allocate (entry->search_icon, &icon_alloc, baseline);
text_alloc.width -= icon_width + spacing;
text_alloc.x += is_rtl ? 0 : icon_width + spacing;
if (gtk_widget_get_child_visible (entry->clear_icon))
{
gtk_widget_measure (entry->clear_icon,
GTK_ORIENTATION_HORIZONTAL,
-1,
NULL, &icon_width,
NULL, NULL);
icon_alloc.x = is_rtl ? 0 : width - icon_width;
icon_alloc.y = 0;
icon_alloc.width = icon_width;
icon_alloc.height = height;
gtk_widget_size_allocate (entry->clear_icon, &icon_alloc, baseline);
text_alloc.width -= icon_width + spacing;
text_alloc.x += is_rtl ? icon_width + spacing : 0;
}
gtk_widget_size_allocate (entry->entry, &text_alloc, baseline);
}
static void
gtk_search_entry_class_init (GtkSearchEntryClass *klass)
{
@ -294,6 +423,8 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass)
widget_class->grab_focus = gtk_search_entry_grab_focus;
widget_class->focus = gtk_widget_focus_child;
widget_class->mnemonic_activate = gtk_search_entry_mnemonic_activate;
widget_class->measure = gtk_search_entry_measure;
widget_class->size_allocate = gtk_search_entry_size_allocate;
klass->stop_search = gtk_search_entry_stop_search;
@ -463,7 +594,6 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass)
"stop-search",
NULL);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
gtk_widget_class_set_css_name (widget_class, I_("entry"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_SEARCH_BOX);
}
@ -548,7 +678,8 @@ gtk_search_entry_changed (GtkEditable *editable,
if (str == NULL || *str == '\0')
{
gtk_widget_set_child_visible (entry->icon, FALSE);
gtk_widget_set_child_visible (entry->clear_icon, FALSE);
gtk_widget_queue_allocate (GTK_WIDGET (entry));
if (entry->delayed_changed_id > 0)
{
@ -559,7 +690,8 @@ gtk_search_entry_changed (GtkEditable *editable,
}
else
{
gtk_widget_set_child_visible (entry->icon, TRUE);
gtk_widget_set_child_visible (entry->clear_icon, TRUE);
gtk_widget_queue_allocate (GTK_WIDGET (entry));
/* Queue up the timeout */
reset_timeout (entry);
@ -597,17 +729,16 @@ catchall_click_press (GtkGestureClick *gesture,
static void
gtk_search_entry_init (GtkSearchEntry *entry)
{
GtkWidget *icon;
GtkGesture *press, *catchall;
entry->search_delay = 150;
/* The search icon is purely presentational */
icon = g_object_new (GTK_TYPE_IMAGE,
"accessible-role", GTK_ACCESSIBLE_ROLE_PRESENTATION,
"icon-name", "system-search-symbolic",
NULL);
gtk_widget_set_parent (icon, GTK_WIDGET (entry));
entry->search_icon = g_object_new (GTK_TYPE_IMAGE,
"accessible-role", GTK_ACCESSIBLE_ROLE_PRESENTATION,
"icon-name", "system-search-symbolic",
NULL);
gtk_widget_set_parent (entry->search_icon, GTK_WIDGET (entry));
entry->entry = gtk_text_new ();
gtk_widget_set_parent (entry->entry, GTK_WIDGET (entry));
@ -619,18 +750,18 @@ gtk_search_entry_init (GtkSearchEntry *entry)
g_signal_connect (entry->entry, "notify", G_CALLBACK (notify_cb), entry);
g_signal_connect (entry->entry, "activate", G_CALLBACK (activate_cb), entry);
entry->icon = g_object_new (GTK_TYPE_IMAGE,
"accessible-role", GTK_ACCESSIBLE_ROLE_PRESENTATION,
"icon-name", "edit-clear-symbolic",
NULL);
gtk_widget_set_tooltip_text (entry->icon, _("Clear Entry"));
gtk_widget_set_parent (entry->icon, GTK_WIDGET (entry));
gtk_widget_set_child_visible (entry->icon, FALSE);
entry->clear_icon = g_object_new (GTK_TYPE_IMAGE,
"accessible-role", GTK_ACCESSIBLE_ROLE_PRESENTATION,
"icon-name", "edit-clear-symbolic",
NULL);
gtk_widget_set_tooltip_text (entry->clear_icon, _("Clear Entry"));
gtk_widget_set_parent (entry->clear_icon, GTK_WIDGET (entry));
gtk_widget_set_child_visible (entry->clear_icon, FALSE);
press = gtk_gesture_click_new ();
g_signal_connect (press, "pressed", G_CALLBACK (gtk_search_entry_icon_press), entry);
g_signal_connect (press, "released", G_CALLBACK (gtk_search_entry_icon_release), entry);
gtk_widget_add_controller (entry->icon, GTK_EVENT_CONTROLLER (press));
gtk_widget_add_controller (entry->clear_icon, GTK_EVENT_CONTROLLER (press));
catchall = gtk_gesture_click_new ();
g_signal_connect (catchall, "pressed",

View File

@ -77,6 +77,11 @@ gtk_string_sorter_get_key (GtkExpression *expression,
return NULL;
string = g_value_get_string (&value);
if (string == NULL)
{
g_value_unset (&value);
return NULL;
}
if (ignore_case)
s = g_utf8_casefold (string, -1);

View File

@ -6717,6 +6717,7 @@ gtk_text_set_placeholder_text (GtkText *self,
"css-name", "placeholder",
"xalign", priv->xalign,
"ellipsize", PANGO_ELLIPSIZE_END,
"max-width-chars", 3,
NULL);
gtk_label_set_attributes (GTK_LABEL (priv->placeholder), priv->attrs);
gtk_widget_insert_after (priv->placeholder, GTK_WIDGET (self), NULL);

View File

@ -277,13 +277,14 @@ G_GNUC_END_IGNORE_DEPRECATIONS
* Since: 4.10
*/
void
gtk_uri_launcher_launch (GtkUriLauncher *self,
GtkWindow *parent,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
gtk_uri_launcher_launch (GtkUriLauncher *self,
GtkWindow *parent,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
GError *error = NULL;
g_return_if_fail (GTK_IS_URI_LAUNCHER (self));
@ -299,6 +300,15 @@ gtk_uri_launcher_launch (GtkUriLauncher *self,
return;
}
if (!g_uri_is_valid (self->uri, G_URI_FLAGS_NONE, &error))
{
g_task_return_new_error (task,
GTK_DIALOG_ERROR, GTK_DIALOG_ERROR_FAILED,
"%s is not a valid uri: %s", self->uri, error->message);
g_error_free (error);
return;
}
#ifndef G_OS_WIN32
if (gtk_openuri_portal_is_available ())
gtk_openuri_portal_open_uri_async (self->uri, parent, cancellable, open_done, task);
@ -325,8 +335,8 @@ G_GNUC_END_IGNORE_DEPRECATIONS
*/
gboolean
gtk_uri_launcher_launch_finish (GtkUriLauncher *self,
GAsyncResult *result,
GError **error)
GAsyncResult *result,
GError **error)
{
g_return_val_if_fail (GTK_IS_URI_LAUNCHER (self), FALSE);
g_return_val_if_fail (g_task_is_valid (result, self), FALSE);

View File

@ -1890,7 +1890,7 @@ gtk_widget_class_init (GtkWidgetClass *klass)
* @keyboard_mode: %TRUE if the tooltip was triggered using the keyboard
* @tooltip: a `GtkTooltip`
*
* Emitted when the widgets tooltip is about to be shown.
* Emitted when the widgets tooltip is about to be shown.
*
* This happens when the [property@Gtk.Widget:has-tooltip] property
* is %TRUE and the hover timeout has expired with the cursor hovering
@ -10596,7 +10596,7 @@ gtk_widget_set_overflow (GtkWidget *widget,
* gtk_widget_get_overflow: (attributes org.gtk.Method.get_property=overflow)
* @widget: a `GtkWidget`
*
* Returns the widgets overflow value.
* Returns the widgets overflow value.
*
* Returns: The widget's overflow.
**/
@ -10884,7 +10884,7 @@ _gtk_widget_peek_style_context (GtkWidget *widget)
* The returned object is guaranteed to be the same
* for the lifetime of @widget.
*
* Returns: (transfer none): the widgets `GtkStyleContext`
* Returns: (transfer none): the widgets `GtkStyleContext`
*
* Deprecated: 4.10: Style contexts will be removed in GTK 5
*/
@ -12022,7 +12022,7 @@ gtk_widget_observe_controllers (GtkWidget *widget)
* gtk_widget_get_first_child:
* @widget: a `GtkWidget`
*
* Returns the widgets first child.
* Returns the widgets first child.
*
* This API is primarily meant for widget implementations.
*
@ -12042,7 +12042,7 @@ gtk_widget_get_first_child (GtkWidget *widget)
* gtk_widget_get_last_child:
* @widget: a `GtkWidget`
*
* Returns the widgets last child.
* Returns the widgets last child.
*
* This API is primarily meant for widget implementations.
*
@ -12062,7 +12062,7 @@ gtk_widget_get_last_child (GtkWidget *widget)
* gtk_widget_get_next_sibling:
* @widget: a `GtkWidget`
*
* Returns the widgets next sibling.
* Returns the widgets next sibling.
*
* This API is primarily meant for widget implementations.
*
@ -12082,7 +12082,7 @@ gtk_widget_get_next_sibling (GtkWidget *widget)
* gtk_widget_get_prev_sibling:
* @widget: a `GtkWidget`
*
* Returns the widgets previous sibling.
* Returns the widgets previous sibling.
*
* This API is primarily meant for widget implementations.
*
@ -12901,7 +12901,7 @@ gtk_widget_get_css_name (GtkWidget *self)
*
* Adds a style class to @widget.
*
* After calling this function, the widgets style will match
* After calling this function, the widgets style will match
* for @css_class, according to CSS matching rules.
*
* Use [method@Gtk.Widget.remove_css_class] to remove the
@ -13040,11 +13040,11 @@ gtk_widget_set_css_classes (GtkWidget *widget,
* @widget: a `GtkWidget`
* @color: (out): return location for the color
*
* Gets the current foreground color for the widgets
* Gets the current foreground color for the widgets
* CSS style.
*
* This function should only be used in snapshot
* implementations that need need to do custom
* implementations that need to do custom
* drawing with the foreground color.
*
* Since: 4.10

View File

@ -5931,6 +5931,9 @@ gtk_window_get_mnemonics_visible (GtkWindow *window)
* @setting: the new value
*
* Sets whether mnemonics are supposed to be visible.
*
* This property is maintained by GTK based on user input,
* and should not be set by applications.
*/
void
gtk_window_set_mnemonics_visible (GtkWindow *window,
@ -6016,11 +6019,14 @@ unset_focus_visible (gpointer data)
}
/**
* gtk_window_set_focus_visible: (attributes org.gtk.MEthod.set_property=focus-visible)
* gtk_window_set_focus_visible: (attributes org.gtk.Method.set_property=focus-visible)
* @window: a `GtkWindow`
* @setting: the new value
*
* Sets whether focus rectangles are supposed to be visible.
*
* This property is maintained by GTK based on user input,
* and should not be set by applications.
*/
void
gtk_window_set_focus_visible (GtkWindow *window,

View File

@ -4543,7 +4543,7 @@ void *convert_run_optimize(void *c, uint8_t typecode_original,
int long_ctr = 0;
uint64_t cur_word = c_qua_bitset->array[0];
int run_count = 0;
G_GNUC_UNUSED int run_count = 0;
while (true) {
while (cur_word == UINT64_C(0) &&
long_ctr < BITSET_CONTAINER_SIZE_IN_WORDS - 1)

View File

@ -57,6 +57,7 @@
<child>
<object class="GtkVolumeButton" id="volume_button">
<property name="adjustment">volume_adjustment</property>
<property name="valign">center</property>
</object>
</child>
</object>

View File

@ -449,6 +449,8 @@ test_data = [
'radial-positions.errors',
'radial-positions.ref.css',
'radial.ref.css',
'resource-url.css',
'resource-url.ref.css',
'rotate3d-crash.css',
'rotate3d-crash.errors',
'rotate3d-crash.ref.css',

View File

@ -0,0 +1,3 @@
window { background-image: url("resource://"); }
button { background-image: url("resource://doesnotexist.jpg"); }

View File

@ -0,0 +1,7 @@
window {
background-image: none /* invalid image */;
}
button {
background-image: none /* invalid image */;
}

View File

@ -717,6 +717,60 @@ test_enabled (void)
g_object_unref (g_object_ref_sink (text));
}
#define MY_TYPE_GTK_ACTIONABLE (my_gtk_actionable_get_type ())
G_DECLARE_FINAL_TYPE (MyGtkActionable, my_gtk_actionable, MY, GTK_ACTIONABLE, GtkButton)
struct _MyGtkActionable
{
GtkButton parent_instance;
};
G_DEFINE_FINAL_TYPE (MyGtkActionable, my_gtk_actionable, GTK_TYPE_BUTTON);
static void
test_cb (GtkWidget *sender,
const char *name,
GVariant *param)
{
}
static void
my_gtk_actionable_init (MyGtkActionable *actionable)
{
gtk_actionable_set_action_name (GTK_ACTIONABLE (actionable), "test.test");
}
static void
my_gtk_actionable_class_init (MyGtkActionableClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
gtk_widget_class_install_action (widget_class, "test.test", NULL, test_cb);
}
/* Test that actions are correctly notified after reparenting */
static void
test_reparenting (void)
{
GtkWidget *window, *actionable;
window = gtk_window_new ();
actionable = g_object_new (MY_TYPE_GTK_ACTIONABLE, NULL);
gtk_window_set_child (GTK_WINDOW (window), actionable);
g_assert_true (gtk_widget_get_sensitive (actionable));
g_object_ref (actionable);
gtk_window_set_child (GTK_WINDOW (window), NULL);
g_assert_false (gtk_widget_get_sensitive (actionable));
gtk_window_set_child (GTK_WINDOW (window), actionable);
g_object_unref (actionable);
g_assert_true (gtk_widget_get_sensitive (actionable));
g_object_unref (window);
}
int
main (int argc,
char *argv[])
@ -732,6 +786,7 @@ main (int argc,
g_test_add_func ("/action/overlap2", test_overlap2);
g_test_add_func ("/action/introspection", test_introspection);
g_test_add_func ("/action/enabled", test_enabled);
g_test_add_func ("/action/reparenting", test_reparenting);
return g_test_run();
}

View File

@ -3,12 +3,8 @@ if bash.found()
test_env = environment()
foreach t : ['simplify', 'simplify-3to4', 'validate', 'settings']
configure_file(output: t,
input: '@0@.in'.format(t),
copy: true,
)
test(t, bash,
args: t,
test(t,
find_program(t, dirs: meson.current_source_dir()),
workdir: meson.current_build_dir(),
protocol: 'tap',
env: [