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" " }\n"
" transform: translate(0, 140);\n" " transform: translate(0, 140);\n"
"}", -1); "}", -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 * NodeEditorWindow *

View File

@ -220,6 +220,6 @@ clipboard.cut, clipboard.copy, clipboard.paste
selection.delete, selection.select-all selection.delete, selection.select-all
: Selection operations on entries, text view and labels : 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 : 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-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: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_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: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: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) | | | 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 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 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 “keyboard navigation”).
to the next location, and <kbd>Shift</kbd>+<kbd>Tab</kbd> to move it back to the previous GTK reserves the <kbd>Tab</kbd> key to move the focus to the next location,
one. In addition many containers allow “directional navigation” with and <kbd>Shift</kbd>+<kbd>Tab</kbd> to move it back to the previous one.
the arrow keys. In addition many containers allow “directional navigation” with the arrow keys.
Many widgets can be “activated” to trigger and action. E.g., you can Many widgets can be “activated” to trigger and action.
activate a button or switch by clicking on them, but you can also E.g., you can activate a button or switch by clicking on them,
activate them with the keyboard, by using the <kbd>Enter</kbd> or <kbd></kbd> keys. 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 Apart from keyboard navigation, activation and directly typing into
entries or text views, GTK widgets can use key events for activating 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 - Accelerators are any other shortcuts that can be activated regardless
of where the focus is, and typically trigger global actions, such as of where the focus is, and typically trigger global actions, such as
Ctrl-Q to quit an application. <kbd>Ctrl</kbd>+<kbd>Q</kbd> to quit an application.
- Mnemonics are usually triggered using Alt as a modifier for a letter. - 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, 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 and are indicated by underlining the letter in the label. As a special
case, inside menus (i.e. inside `GtkPopoverMenu`), mnemonics can be case, inside menus (i.e. inside `GtkPopoverMenu`), mnemonics can be
triggered without the modifier. triggered without the modifier.
- Key bindings are specific to individual widgets, such as Ctrl-C or - Key bindings are specific to individual widgets,
Ctrl-V in an entry copy to or paste from the clipboard. They are only such as <kbd>Ctrl</kbd>+<kbd>C</kbd> or <kbd>Ctrl</kbd>+<kbd>V</kbd>
triggered when the widget has focus. 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 GTK handles accelerators and mnemonics in a global scope, during the
capture phase, and key bindings locally, during the target phase. 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 the others. They also are mutually exclusive, within a widget
where may be only one gesture group claiming a given sequence. where may be only one gesture group claiming a given sequence.
If another gesture group claims later that same sequence, the 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); priv->surface->paint_context = g_object_ref (context);
GDK_DRAW_CONTEXT_GET_CLASS (context)->begin_frame (context, prefers_high_depth, priv->frame_region); 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 #ifdef HAVE_SYSPROF

View File

@ -165,7 +165,7 @@ parse_rgb_value (const char *str,
* *
* The string can be either one of: * 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, * - A hexadecimal value in the form \#rgb, \#rrggbb,
* \#rrrgggbbb or \#rrrrggggbbbb * \#rrrgggbbb or \#rrrrggggbbbb
* - A hexadecimal value in the form \#rgba, \#rrggbbaa, * - 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 * - A RGB color in the form rgb(r,g,b) (In this case the color
* will have full opacity) * will have full opacity)
* - A RGBA color in the form rgba(r,g,b,a) * - 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, * Where r, g, b and a are respectively the red, green,
* blue and alpha color values. In the last two cases, r, g, * 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; char *path;
XcursorImages *images; XcursorImages *images;
struct cursor *cursor; struct wl_cursor *cursor;
struct cursor_image *image; struct cursor_image *image;
int i, nbytes; int i, nbytes;
unsigned int load_size; unsigned int load_size;
@ -240,17 +240,16 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
return NULL; return NULL;
} }
cursor->cursor.images = cursor->images =
malloc(images->nimage * sizeof cursor->cursor.images[0]); malloc(images->nimage * sizeof cursor->images[0]);
if (!cursor->cursor.images) { if (!cursor->images) {
free(cursor); free(cursor);
xcursor_images_destroy (images); xcursor_images_destroy (images);
return NULL; return NULL;
} }
cursor->cursor.name = strdup(name); cursor->name = strdup(name);
cursor->cursor.size = load_size; cursor->size = load_size;
cursor->total_delay = 0;
for (i = 0; i < images->nimage; i++) { for (i = 0; i < images->nimage; i++) {
image = malloc(sizeof *image); 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->images[i] = (struct wl_cursor_image *) image;
cursor->cursor.images[i] = (struct wl_cursor_image *) image;
} }
cursor->cursor.image_count = i; cursor->image_count = i;
if (cursor->cursor.image_count == 0) { if (cursor->image_count == 0) {
free(cursor->cursor.name); free(cursor->name);
free(cursor->cursor.images); free(cursor->images);
free(cursor); free(cursor);
xcursor_images_destroy (images); xcursor_images_destroy (images);
return NULL; return NULL;
@ -306,7 +304,7 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
xcursor_images_destroy (images); xcursor_images_destroy (images);
return &cursor->cursor; return cursor;
} }
static void static void

View File

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

View File

@ -145,7 +145,8 @@ struct _GdkX11Display
guint server_time_is_monotonic_time : 1; guint server_time_is_monotonic_time : 1;
/* GLX extensions we check */ /* 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_create_context : 1;
guint has_glx_texture_from_pixmap : 1; guint has_glx_texture_from_pixmap : 1;
guint has_glx_video_sync : 1; guint has_glx_video_sync : 1;

View File

@ -134,35 +134,6 @@ struct _GdkX11DragClass
GdkDragClass parent_class; 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 */ /* Forward declarations */
static GdkSurfaceCache *gdk_surface_cache_ref (GdkSurfaceCache *cache); static GdkSurfaceCache *gdk_surface_cache_ref (GdkSurfaceCache *cache);
@ -1899,20 +1870,15 @@ drag_grab (GdkDrag *drag)
{ {
GdkX11Drag *x11_drag = GDK_X11_DRAG (drag); GdkX11Drag *x11_drag = GDK_X11_DRAG (drag);
GdkSeatCapabilities capabilities; GdkSeatCapabilities capabilities;
GdkDisplay *display;
Window root;
GdkSeat *seat; GdkSeat *seat;
int keycode, i;
GdkCursor *cursor; GdkCursor *cursor;
if (!x11_drag->ipc_surface) if (!x11_drag->ipc_surface)
return FALSE; return FALSE;
display = gdk_drag_get_display (drag);
root = GDK_DISPLAY_XROOTWIN (display);
seat = gdk_device_get_seat (gdk_drag_get_device (drag)); 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); cursor = gdk_drag_get_cursor (drag, x11_drag->current_action);
g_set_object (&x11_drag->cursor, cursor); g_set_object (&x11_drag->cursor, cursor);
@ -1924,46 +1890,6 @@ drag_grab (GdkDrag *drag)
g_set_object (&x11_drag->grab_seat, seat); 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; return TRUE;
} }
@ -1971,41 +1897,13 @@ static void
drag_ungrab (GdkDrag *drag) drag_ungrab (GdkDrag *drag)
{ {
GdkX11Drag *x11_drag = GDK_X11_DRAG (drag); GdkX11Drag *x11_drag = GDK_X11_DRAG (drag);
GdkDisplay *display;
GdkDevice *keyboard;
Window root;
int keycode, i;
if (!x11_drag->grab_seat) if (!x11_drag->grab_seat)
return; return;
gdk_seat_ungrab (x11_drag->grab_seat); 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); 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 * GdkDrag *
@ -2232,103 +2130,6 @@ gdk_dnd_handle_motion_event (GdkDrag *drag,
return TRUE; 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 static gboolean
gdk_dnd_handle_grab_broken_event (GdkDrag *drag, gdk_dnd_handle_grab_broken_event (GdkDrag *drag,
GdkEvent *event) GdkEvent *event)
@ -2395,10 +2196,6 @@ gdk_x11_drag_handle_event (GdkDrag *drag,
case GDK_BUTTON_RELEASE: case GDK_BUTTON_RELEASE:
return gdk_dnd_handle_button_event (drag, event); 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: case GDK_GRAB_BROKEN:
return gdk_dnd_handle_grab_broken_event (drag, event); 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) if (display_x11->has_glx_video_sync)
glXGetVideoSyncSGI (&end_frame_counter); 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 (); glFinish ();
@ -249,7 +249,7 @@ gdk_x11_gl_context_glx_make_current (GdkGLContext *context,
if (!glXMakeContextCurrent (dpy, drawable, drawable, self->glx_context)) if (!glXMakeContextCurrent (dpy, drawable, drawable, self->glx_context))
return FALSE; 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 /* If the WM is compositing there is no particular need to delay
* the swap when drawing on the offscreen, rendering to the screen * 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. */ * to the vblank. */
do_frame_sync = ! gdk_display_is_composited (display); 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) if (do_frame_sync)
glXSwapIntervalSGI (1); glXSwapIntervalEXT (dpy, drawable, 1);
else else
glXSwapIntervalSGI (0); 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"); epoxy_has_glx_extension (dpy, screen_num, "GLX_ARB_create_context_profile");
display_x11->has_glx_create_es2_context = display_x11->has_glx_create_es2_context =
epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_create_context_es2_profile"); 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"); 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 = display_x11->has_glx_texture_from_pixmap =
epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_texture_from_pixmap"); epoxy_has_glx_extension (dpy, screen_num, "GLX_EXT_texture_from_pixmap");
display_x11->has_glx_video_sync = 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_ARB_create_context_profile: %s\n"
"\t* GLX_EXT_create_context_es2_profile: %s\n" "\t* GLX_EXT_create_context_es2_profile: %s\n"
"\t* GLX_SGI_swap_control: %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_EXT_texture_from_pixmap: %s\n"
"\t* GLX_SGI_video_sync: %s\n" "\t* GLX_SGI_video_sync: %s\n"
"\t* GLX_EXT_buffer_age: %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), glXGetClientString (dpy, GLX_VENDOR),
display_x11->has_glx_create_context ? "yes" : "no", display_x11->has_glx_create_context ? "yes" : "no",
display_x11->has_glx_create_es2_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_texture_from_pixmap ? "yes" : "no",
display_x11->has_glx_video_sync ? "yes" : "no", display_x11->has_glx_video_sync ? "yes" : "no",
display_x11->has_glx_buffer_age ? "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) for (i = 0; i < resources->noutput; ++i)
{ {
RROutput output = resources->outputs[i]; RROutput output = resources->outputs[i];
XRROutputInfo *output_info = XRROutputInfo *output_info;
XRRGetOutputInfo (x11_screen->xdisplay, resources, output);
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) if (output_info->connection == RR_Disconnected)
{ {
@ -697,13 +702,22 @@ init_randr13 (GdkX11Screen *x11_screen)
if (output_info->crtc) if (output_info->crtc)
{ {
GdkX11Monitor *monitor; GdkX11Monitor *monitor;
XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc); XRRCrtcInfo *crtc;
char *name; char *name;
GdkRectangle geometry; GdkRectangle geometry;
GdkRectangle newgeo; GdkRectangle newgeo;
int j; int j;
int refresh_rate = 0; 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++) for (j = 0; j < resources->nmode; j++)
{ {
XRRModeInfo *xmode = &resources->modes[j]; XRRModeInfo *xmode = &resources->modes[j];
@ -775,8 +789,10 @@ init_randr13 (GdkX11Screen *x11_screen)
} }
x11_display->primary_monitor = 0; x11_display->primary_monitor = 0;
gdk_x11_display_error_trap_push (display);
primary_output = XRRGetOutputPrimary (x11_screen->xdisplay, primary_output = XRRGetOutputPrimary (x11_screen->xdisplay,
x11_screen->xroot_window); 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++) 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) if (size == 0)
{ {
/* EOF marker, put it back */ /* 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; break;
} }
else if (size > count) 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); memcpy (buffer, g_bytes_get_data (bytes, NULL), size);
} }
g_bytes_unref (bytes); g_bytes_unref (g_steal_pointer (&bytes));
result += size; result += size;
if (buffer) if (buffer)
buffer += size; 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); GDK_X11_DISPLAY (priv->display)->streams = g_slist_remove (GDK_X11_DISPLAY (priv->display)->streams, stream);
g_signal_handlers_disconnect_by_func (priv->display, g_signal_handlers_disconnect_by_func (priv->display,
gdk_x11_selection_input_stream_xevent, gdk_x11_selection_input_stream_xevent,
stream); g_steal_pointer (&stream));
g_object_unref (stream);
} }
static gssize static gssize
@ -416,7 +414,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
"%s:%s: got PropertyNotify erroring out of INCR", "%s:%s: got PropertyNotify erroring out of INCR",
priv->selection, priv->target); priv->selection, priv->target);
/* error, should we signal one? */ /* 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) 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", "%s:%s: got PropertyNotify ending INCR",
priv->selection, priv->target); priv->selection, priv->target);
g_bytes_unref (bytes); g_bytes_unref (bytes);
gdk_x11_selection_input_stream_complete (stream); g_clear_pointer (&stream, gdk_x11_selection_input_stream_complete);
} }
else else
{ {
@ -467,7 +465,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
G_IO_ERROR, G_IO_ERROR,
G_IO_ERROR_NOT_FOUND, G_IO_ERROR_NOT_FOUND,
_("Format %s not supported"), priv->target); _("Format %s not supported"), priv->target);
gdk_x11_selection_input_stream_complete (stream); g_clear_pointer (&stream, gdk_x11_selection_input_stream_complete);
} }
else else
{ {
@ -478,7 +476,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
if (bytes == NULL) if (bytes == NULL)
{ {
gdk_x11_selection_input_stream_complete (stream); g_clear_pointer (&stream, gdk_x11_selection_input_stream_complete);
} }
else else
{ {
@ -500,7 +498,7 @@ gdk_x11_selection_input_stream_xevent (GdkDisplay *display,
g_bytes_get_size (bytes)); g_bytes_get_size (bytes));
g_async_queue_push (priv->chunks, 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->property = g_strdup_printf ("GDK_SELECTION_%p", stream);
priv->xproperty = gdk_x11_get_xatom_by_name_for_display (display, priv->property); 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), XConvertSelection (GDK_DISPLAY_XDISPLAY (display),
priv->xselection, priv->xselection,
@ -577,7 +578,6 @@ gdk_x11_selection_input_stream_new_finish (GAsyncResult *result,
*type = priv->type; *type = priv->type;
if (format) if (format)
*format = priv->format; *format = priv->format;
g_object_ref (stream);
} }
return G_INPUT_STREAM (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 (GSK_IS_GL_COMMAND_QUEUE (self));
g_assert (self->batches.len > 0); g_assert (self->batches.len > 0);
if (will_ignore_batch (self))
return;
g_assert (self->in_draw == TRUE); g_assert (self->in_draw == TRUE);
program = self->program_info; program = self->program_info;

View File

@ -377,6 +377,8 @@ gsk_renderer_render_texture (GskRenderer *renderer,
gsk_render_node_get_bounds (root, &real_viewport); gsk_render_node_get_bounds (root, &real_viewport);
viewport = &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); 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); pattern = cairo_pop_group (cr);
cairo_restore (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++) for (i = 0; i < self->n_shadows; i++)
{ {
GskShadow *shadow = &self->shadows[i]; GskShadow *shadow = &self->shadows[i];
@ -4129,6 +4134,7 @@ gsk_shadow_node_draw (GskRenderNode *node,
cairo_set_source (cr, pattern); cairo_set_source (cr, pattern);
cairo_paint (cr); cairo_paint (cr);
cairo_restore (cr);
cairo_pattern_destroy (pattern); cairo_pattern_destroy (pattern);
} }

View File

@ -325,6 +325,9 @@ gtk_action_muxer_get_group (GtkActionMuxer *muxer,
{ {
Group *group; Group *group;
if (!muxer->groups)
return NULL;
group = g_hash_table_lookup (muxer->groups, group_name); group = g_hash_table_lookup (muxer->groups, group_name);
if (group) if (group)
return group->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)); 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, &enabled, &parameter_type,
NULL, NULL, &state, NULL, NULL, &state,
TRUE)) TRUE))

View File

@ -88,7 +88,7 @@ gtk_css_value_corner_transition (GtkCssValue *start,
static void static void
gtk_css_value_corner_print (const GtkCssValue *corner, gtk_css_value_corner_print (const GtkCssValue *corner,
GString *string) GString *string)
{ {
_gtk_css_value_print (corner->x, string); _gtk_css_value_print (corner->x, string);
if (!_gtk_css_value_equal (corner->x, corner->y)) 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 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 * GtkCssValue *
_gtk_css_corner_value_new (GtkCssValue *x, _gtk_css_corner_value_new (GtkCssValue *x,
GtkCssValue *y) GtkCssValue *y)
{ {
GtkCssValue *result; 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); initialize_corner_singletons ();
return x;
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); result = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_CORNER);
@ -162,9 +201,6 @@ double
_gtk_css_corner_value_get_x (const GtkCssValue *corner, _gtk_css_corner_value_get_x (const GtkCssValue *corner,
double one_hundred_percent) 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 != NULL, 0.0);
g_return_val_if_fail (corner->class == &GTK_CSS_VALUE_CORNER, 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, _gtk_css_corner_value_get_y (const GtkCssValue *corner,
double one_hundred_percent) 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 != NULL, 0.0);
g_return_val_if_fail (corner->class == &GTK_CSS_VALUE_CORNER, 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); g_hash_table_iter_init (&iter, value1->features);
while (g_hash_table_iter_next (&iter, &name, &val1)) 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) if (val1 != val2)
return FALSE; return FALSE;
@ -106,11 +107,10 @@ gtk_css_value_font_features_transition (GtkCssValue *start,
g_hash_table_iter_init (&iter, start->features); g_hash_table_iter_init (&iter, start->features);
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&start_val)) while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&start_val))
{ {
end_val = g_hash_table_lookup (end->features, name); if (!g_hash_table_lookup_extended (end->features, name, NULL, &end_val))
if (end_val == NULL)
transition = start_val; transition = start_val;
else 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)); 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); g_hash_table_iter_init (&iter, end->features);
while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&end_val)) while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&end_val))
{ {
start_val = g_hash_table_lookup (start->features, name); if (g_hash_table_lookup_extended (end->features, name, NULL, &start_val))
if (start_val != NULL)
continue; continue;
gtk_css_font_features_value_add_feature (result, name, GPOINTER_TO_INT (end_val)); 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; return url->loaded_image;
} }
/* We special case resources here so we can use gdk_texture_new_from_resource. */ texture = gdk_texture_new_from_file (url->file, &local_error);
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);
}
if (texture == NULL) 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, 2 }} },
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 3 }} }, { &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, 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, 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, 16 }} }, /* Icon size default */
{ &GTK_CSS_VALUE_NUMBER, 1, TRUE, TYPE_DIMENSION, {{ GTK_CSS_PX, 32 }} }, { &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 == 1 ||
value == 2 || value == 2 ||
value == 3 || value == 3 ||
value == 4) value == 4 ||
value == 5 ||
value == 6 ||
value == 7 ||
value == 8)
return _gtk_css_value_ref (&px_singletons[(int) value]); return _gtk_css_value_ref (&px_singletons[(int) value]);
if (value == 8)
return _gtk_css_value_ref (&px_singletons[5]);
if (value == 16) if (value == 16)
return _gtk_css_value_ref (&px_singletons[6]); return _gtk_css_value_ref (&px_singletons[9]);
if (value == 32) if (value == 32)
return _gtk_css_value_ref (&px_singletons[7]); return _gtk_css_value_ref (&px_singletons[10]);
if (value == 64) if (value == 64)
return _gtk_css_value_ref (&px_singletons[8]); return _gtk_css_value_ref (&px_singletons[11]);
break; break;

View File

@ -336,10 +336,10 @@ gtk_css_shadow_value_new_filter (const GtkCssValue *other)
ShadowValue value; ShadowValue value;
value.inset = FALSE; value.inset = FALSE;
value.hoffset = _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_NUMBER); value.voffset = _gtk_css_number_value_new (0, GTK_CSS_PX);
value.radius = _gtk_css_number_value_new (0, GTK_CSS_NUMBER); value.radius = _gtk_css_number_value_new (0, GTK_CSS_PX);
value.spread = _gtk_css_number_value_new (0, GTK_CSS_NUMBER); value.spread = _gtk_css_number_value_new (0, GTK_CSS_PX);
value.color = gtk_css_value_ref (other->shadows[0].color); value.color = gtk_css_value_ref (other->shadows[0].color);
return gtk_css_shadow_value_new (&value, 1, TRUE); 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: case GTK_CSS_TRANSFORM_ROTATE:
transform->rotate.x = _gtk_css_number_value_new (0, GTK_CSS_NUMBER); 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.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); transform->rotate.angle = _gtk_css_number_value_new (0, GTK_CSS_DEG);
break; break;
case GTK_CSS_TRANSFORM_SCALE: case GTK_CSS_TRANSFORM_SCALE:

View File

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

View File

@ -40,7 +40,7 @@
* expanded widget yourself, such as when you want to actually create * expanded widget yourself, such as when you want to actually create
* the widget at expansion time. In this case, create a `GtkExpander` * the widget at expansion time. In this case, create a `GtkExpander`
* but do not add a child to it. The expander widget has an * 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 * monitor its expansion state. You should watch this property with
* a signal connection as follows: * 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); stop_loading_and_clear_list_model (impl, FALSE);
search_clear_model (impl, FALSE); search_clear_model (impl, FALSE);
recent_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->model_for_search);
g_clear_object (&impl->browse_files_model);
g_clear_object (&impl->selection_model); g_clear_object (&impl->selection_model);
g_clear_object (&impl->sort_model); g_clear_object (&impl->sort_model);
@ -3981,6 +3984,7 @@ set_list_model (GtkFileChooserWidget *impl,
set_busy_cursor (impl, TRUE); set_busy_cursor (impl, TRUE);
g_clear_object (&impl->browse_files_model);
impl->browse_files_model = impl->browse_files_model =
_gtk_file_system_model_new_for_directory (impl->current_folder, MODEL_ATTRIBUTES); _gtk_file_system_model_new_for_directory (impl->current_folder, MODEL_ATTRIBUTES);

View File

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

View File

@ -1970,10 +1970,13 @@ gtk_label_activate_link_open (GtkWidget *widget,
GVariant *parameter) GVariant *parameter)
{ {
GtkLabel *self = GTK_LABEL (widget); 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) if (link)
emit_activate_link (self, link); emit_activate_link (self, link);
}
} }
static void static void
@ -1982,17 +1985,18 @@ gtk_label_activate_link_copy (GtkWidget *widget,
GVariant *parameter) GVariant *parameter)
{ {
GtkLabel *self = GTK_LABEL (widget); GtkLabel *self = GTK_LABEL (widget);
GtkLabelLink *link = self->select_info->context_link; if (self->select_info)
if (link)
{ {
GdkClipboard *clipboard; GtkLabelLink *link = self->select_info->context_link;
clipboard = gtk_widget_get_clipboard (widget); if (link)
gdk_clipboard_set_text (clipboard, link->uri); {
GdkClipboard *clipboard;
clipboard = gtk_widget_get_clipboard (widget);
gdk_clipboard_set_text (clipboard, link->uri);
}
} }
else
g_print ("no link ?!\n");
} }
static void 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) * gtk_menu_button_set_always_show_arrow: (attributes org.gtk.Method.set_property=always-show-arrow)
* @menu_button: a `GtkMenuButton` * @menu_button: a `GtkMenuButton`
* @always_show_arrow: whether to show a dropdown arrow even when using an icon * @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 * Sets whether to show a dropdown arrow even when using an icon or a custom
* child. * 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) * gtk_menu_button_get_always_show_arrow: (attributes org.gtk.Method.get_property=always-show-arrow)
* @menu_button: a `GtkMenuButton` * @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 * Since: 4.4
*/ */
@ -1526,7 +1529,7 @@ gtk_menu_button_get_child (GtkMenuButton *menu_button)
* @menu_button: a `GtkMenuButton` * @menu_button: a `GtkMenuButton`
* @active: whether the menu button is active * @active: whether the menu button is active
* *
* Sets whether menu button acts is active. * Sets whether the menu button is active.
* *
* Since: 4.10 * 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_orientable_set_orientation (GTK_ORIENTABLE (box->item_box), GTK_ORIENTATION_HORIZONTAL);
gtk_widget_add_css_class (GTK_WIDGET (box->item_box), "inline-buttons"); 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_box_append (GTK_BOX (box->item_box), spacer);
gtk_size_group_add_widget (box->indicators, 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; 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, g_object_class_install_property (object_class,
PROP_CHILD, PROP_CHILD,
g_param_spec_object ("child", NULL, NULL, g_param_spec_object ("child", NULL, NULL,

View File

@ -129,6 +129,7 @@
#include "gtkroundedboxprivate.h" #include "gtkroundedboxprivate.h"
#include "gsk/gskroundedrectprivate.h" #include "gsk/gskroundedrectprivate.h"
#include "gtkcssshadowvalueprivate.h" #include "gtkcssshadowvalueprivate.h"
#include "gtkcsscornervalueprivate.h"
#include "gdk/gdksurfaceprivate.h" #include "gdk/gdksurfaceprivate.h"
@ -1193,6 +1194,16 @@ gtk_popover_finalize (GObject *object)
G_OBJECT_CLASS (gtk_popover_parent_class)->finalize (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 static void
gtk_popover_get_gap_coords (GtkPopover *popover, gtk_popover_get_gap_coords (GtkPopover *popover,
int *initial_x_out, int *initial_x_out,
@ -1227,7 +1238,7 @@ gtk_popover_get_gap_coords (GtkPopover *popover,
pos = priv->final_position; pos = priv->final_position;
style = gtk_css_node_get_style (gtk_widget_get_css_node (priv->contents_widget)); 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_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_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); 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); 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 static int
get_minimal_size (GtkPopover *popover, get_minimal_size (GtkPopover *popover,
GtkOrientation orientation) GtkOrientation orientation)
@ -1443,7 +1445,7 @@ get_minimal_size (GtkPopover *popover,
int tail_gap_width = priv->has_arrow ? TAIL_GAP_WIDTH : 0; int tail_gap_width = priv->has_arrow ? TAIL_GAP_WIDTH : 0;
int min_width, min_height; 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; pos = priv->position;
if ((orientation == GTK_ORIENTATION_HORIZONTAL && POS_IS_VERTICAL (pos)) || 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; break;
case PROP_PROPERTY: case PROP_PROPERTY:
g_value_set_object (value, self->property); g_value_set_string (value, self->property);
break; break;
default: default:
@ -408,7 +408,7 @@ gtk_property_lookup_list_model_class_init (GtkPropertyLookupListModelClass *klas
*/ */
properties[PROP_OBJECT] = properties[PROP_OBJECT] =
g_param_spec_object ("object", NULL, NULL, g_param_spec_object ("object", NULL, NULL,
G_TYPE_LIST_MODEL, G_TYPE_OBJECT,
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY); GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, NUM_PROPERTIES, properties); 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 static void
gtk_property_lookup_list_model_init (GtkPropertyLookupListModel *self) gtk_property_lookup_list_model_init (GtkPropertyLookupListModel *self)
{ {
self->item_type = G_TYPE_OBJECT;
self->items = g_ptr_array_new (); self->items = g_ptr_array_new ();
/* add sentinel */ /* add sentinel */
g_ptr_array_add (self->items, NULL); 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_strfreev (uris);
g_date_time_unref (now);
} }
static void static void
@ -2180,13 +2181,16 @@ gtk_recent_info_get_uri_display (GtkRecentInfo *info)
int int
gtk_recent_info_get_age (GtkRecentInfo *info) gtk_recent_info_get_age (GtkRecentInfo *info)
{ {
int diff;
GDateTime *now; GDateTime *now;
g_return_val_if_fail (info != NULL, -1); g_return_val_if_fail (info != NULL, -1);
now = g_date_time_new_now_utc (); 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)) if (priv->child && gtk_widget_get_visible (priv->child))
{ {
int min_child_size, nat_child_size; 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, &min_child_size, &nat_child_size,
NULL, NULL); NULL, NULL);

View File

@ -40,7 +40,8 @@
#include "gtkmarshalers.h" #include "gtkmarshalers.h"
#include "gtkeventcontrollerkey.h" #include "gtkeventcontrollerkey.h"
#include "gtkwidgetprivate.h" #include "gtkwidgetprivate.h"
#include "gtkcssnodeprivate.h"
#include "gtkcsspositionvalueprivate.h"
/** /**
* GtkSearchEntry: * GtkSearchEntry:
@ -124,8 +125,9 @@ struct _GtkSearchEntry
guint search_delay; guint search_delay;
GtkWidget *search_icon;
GtkWidget *entry; GtkWidget *entry;
GtkWidget *icon; GtkWidget *clear_icon;
guint delayed_changed_id; guint delayed_changed_id;
gboolean content_changed; gboolean content_changed;
@ -165,10 +167,9 @@ gtk_search_entry_finalize (GObject *object)
gtk_editable_finish_delegate (GTK_EDITABLE (entry)); 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->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) if (entry->delayed_changed_id > 0)
g_source_remove (entry->delayed_changed_id); g_source_remove (entry->delayed_changed_id);
@ -281,6 +282,134 @@ gtk_search_entry_mnemonic_activate (GtkWidget *widget,
return TRUE; 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 static void
gtk_search_entry_class_init (GtkSearchEntryClass *klass) 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->grab_focus = gtk_search_entry_grab_focus;
widget_class->focus = gtk_widget_focus_child; widget_class->focus = gtk_widget_focus_child;
widget_class->mnemonic_activate = gtk_search_entry_mnemonic_activate; 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; klass->stop_search = gtk_search_entry_stop_search;
@ -463,7 +594,6 @@ gtk_search_entry_class_init (GtkSearchEntryClass *klass)
"stop-search", "stop-search",
NULL); 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_css_name (widget_class, I_("entry"));
gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_SEARCH_BOX); 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') 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) if (entry->delayed_changed_id > 0)
{ {
@ -559,7 +690,8 @@ gtk_search_entry_changed (GtkEditable *editable,
} }
else 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 */ /* Queue up the timeout */
reset_timeout (entry); reset_timeout (entry);
@ -597,17 +729,16 @@ catchall_click_press (GtkGestureClick *gesture,
static void static void
gtk_search_entry_init (GtkSearchEntry *entry) gtk_search_entry_init (GtkSearchEntry *entry)
{ {
GtkWidget *icon;
GtkGesture *press, *catchall; GtkGesture *press, *catchall;
entry->search_delay = 150; entry->search_delay = 150;
/* The search icon is purely presentational */ /* The search icon is purely presentational */
icon = g_object_new (GTK_TYPE_IMAGE, entry->search_icon = g_object_new (GTK_TYPE_IMAGE,
"accessible-role", GTK_ACCESSIBLE_ROLE_PRESENTATION, "accessible-role", GTK_ACCESSIBLE_ROLE_PRESENTATION,
"icon-name", "system-search-symbolic", "icon-name", "system-search-symbolic",
NULL); NULL);
gtk_widget_set_parent (icon, GTK_WIDGET (entry)); gtk_widget_set_parent (entry->search_icon, GTK_WIDGET (entry));
entry->entry = gtk_text_new (); entry->entry = gtk_text_new ();
gtk_widget_set_parent (entry->entry, GTK_WIDGET (entry)); 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, "notify", G_CALLBACK (notify_cb), entry);
g_signal_connect (entry->entry, "activate", G_CALLBACK (activate_cb), entry); g_signal_connect (entry->entry, "activate", G_CALLBACK (activate_cb), entry);
entry->icon = g_object_new (GTK_TYPE_IMAGE, entry->clear_icon = g_object_new (GTK_TYPE_IMAGE,
"accessible-role", GTK_ACCESSIBLE_ROLE_PRESENTATION, "accessible-role", GTK_ACCESSIBLE_ROLE_PRESENTATION,
"icon-name", "edit-clear-symbolic", "icon-name", "edit-clear-symbolic",
NULL); NULL);
gtk_widget_set_tooltip_text (entry->icon, _("Clear Entry")); gtk_widget_set_tooltip_text (entry->clear_icon, _("Clear Entry"));
gtk_widget_set_parent (entry->icon, GTK_WIDGET (entry)); gtk_widget_set_parent (entry->clear_icon, GTK_WIDGET (entry));
gtk_widget_set_child_visible (entry->icon, FALSE); gtk_widget_set_child_visible (entry->clear_icon, FALSE);
press = gtk_gesture_click_new (); press = gtk_gesture_click_new ();
g_signal_connect (press, "pressed", G_CALLBACK (gtk_search_entry_icon_press), entry); 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); 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 (); catchall = gtk_gesture_click_new ();
g_signal_connect (catchall, "pressed", g_signal_connect (catchall, "pressed",

View File

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

View File

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

View File

@ -277,13 +277,14 @@ G_GNUC_END_IGNORE_DEPRECATIONS
* Since: 4.10 * Since: 4.10
*/ */
void void
gtk_uri_launcher_launch (GtkUriLauncher *self, gtk_uri_launcher_launch (GtkUriLauncher *self,
GtkWindow *parent, GtkWindow *parent,
GCancellable *cancellable, GCancellable *cancellable,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GTask *task; GTask *task;
GError *error = NULL;
g_return_if_fail (GTK_IS_URI_LAUNCHER (self)); g_return_if_fail (GTK_IS_URI_LAUNCHER (self));
@ -299,6 +300,15 @@ gtk_uri_launcher_launch (GtkUriLauncher *self,
return; 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 #ifndef G_OS_WIN32
if (gtk_openuri_portal_is_available ()) if (gtk_openuri_portal_is_available ())
gtk_openuri_portal_open_uri_async (self->uri, parent, cancellable, open_done, task); gtk_openuri_portal_open_uri_async (self->uri, parent, cancellable, open_done, task);
@ -325,8 +335,8 @@ G_GNUC_END_IGNORE_DEPRECATIONS
*/ */
gboolean gboolean
gtk_uri_launcher_launch_finish (GtkUriLauncher *self, gtk_uri_launcher_launch_finish (GtkUriLauncher *self,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
g_return_val_if_fail (GTK_IS_URI_LAUNCHER (self), FALSE); g_return_val_if_fail (GTK_IS_URI_LAUNCHER (self), FALSE);
g_return_val_if_fail (g_task_is_valid (result, 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 * @keyboard_mode: %TRUE if the tooltip was triggered using the keyboard
* @tooltip: a `GtkTooltip` * @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 * This happens when the [property@Gtk.Widget:has-tooltip] property
* is %TRUE and the hover timeout has expired with the cursor hovering * 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) * gtk_widget_get_overflow: (attributes org.gtk.Method.get_property=overflow)
* @widget: a `GtkWidget` * @widget: a `GtkWidget`
* *
* Returns the widgets overflow value. * Returns the widgets overflow value.
* *
* Returns: The widget's overflow. * 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 * The returned object is guaranteed to be the same
* for the lifetime of @widget. * 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 * 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: * gtk_widget_get_first_child:
* @widget: a `GtkWidget` * @widget: a `GtkWidget`
* *
* Returns the widgets first child. * Returns the widgets first child.
* *
* This API is primarily meant for widget implementations. * This API is primarily meant for widget implementations.
* *
@ -12042,7 +12042,7 @@ gtk_widget_get_first_child (GtkWidget *widget)
* gtk_widget_get_last_child: * gtk_widget_get_last_child:
* @widget: a `GtkWidget` * @widget: a `GtkWidget`
* *
* Returns the widgets last child. * Returns the widgets last child.
* *
* This API is primarily meant for widget implementations. * This API is primarily meant for widget implementations.
* *
@ -12062,7 +12062,7 @@ gtk_widget_get_last_child (GtkWidget *widget)
* gtk_widget_get_next_sibling: * gtk_widget_get_next_sibling:
* @widget: a `GtkWidget` * @widget: a `GtkWidget`
* *
* Returns the widgets next sibling. * Returns the widgets next sibling.
* *
* This API is primarily meant for widget implementations. * This API is primarily meant for widget implementations.
* *
@ -12082,7 +12082,7 @@ gtk_widget_get_next_sibling (GtkWidget *widget)
* gtk_widget_get_prev_sibling: * gtk_widget_get_prev_sibling:
* @widget: a `GtkWidget` * @widget: a `GtkWidget`
* *
* Returns the widgets previous sibling. * Returns the widgets previous sibling.
* *
* This API is primarily meant for widget implementations. * 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. * 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. * for @css_class, according to CSS matching rules.
* *
* Use [method@Gtk.Widget.remove_css_class] to remove the * Use [method@Gtk.Widget.remove_css_class] to remove the
@ -13040,11 +13040,11 @@ gtk_widget_set_css_classes (GtkWidget *widget,
* @widget: a `GtkWidget` * @widget: a `GtkWidget`
* @color: (out): return location for the color * @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. * CSS style.
* *
* This function should only be used in snapshot * 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. * drawing with the foreground color.
* *
* Since: 4.10 * Since: 4.10

View File

@ -5931,6 +5931,9 @@ gtk_window_get_mnemonics_visible (GtkWindow *window)
* @setting: the new value * @setting: the new value
* *
* Sets whether mnemonics are supposed to be visible. * 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 void
gtk_window_set_mnemonics_visible (GtkWindow *window, 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` * @window: a `GtkWindow`
* @setting: the new value * @setting: the new value
* *
* Sets whether focus rectangles are supposed to be visible. * 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 void
gtk_window_set_focus_visible (GtkWindow *window, 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; int long_ctr = 0;
uint64_t cur_word = c_qua_bitset->array[0]; uint64_t cur_word = c_qua_bitset->array[0];
int run_count = 0; G_GNUC_UNUSED int run_count = 0;
while (true) { while (true) {
while (cur_word == UINT64_C(0) && while (cur_word == UINT64_C(0) &&
long_ctr < BITSET_CONTAINER_SIZE_IN_WORDS - 1) long_ctr < BITSET_CONTAINER_SIZE_IN_WORDS - 1)

View File

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

View File

@ -449,6 +449,8 @@ test_data = [
'radial-positions.errors', 'radial-positions.errors',
'radial-positions.ref.css', 'radial-positions.ref.css',
'radial.ref.css', 'radial.ref.css',
'resource-url.css',
'resource-url.ref.css',
'rotate3d-crash.css', 'rotate3d-crash.css',
'rotate3d-crash.errors', 'rotate3d-crash.errors',
'rotate3d-crash.ref.css', '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)); 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 int
main (int argc, main (int argc,
char *argv[]) char *argv[])
@ -732,6 +786,7 @@ main (int argc,
g_test_add_func ("/action/overlap2", test_overlap2); g_test_add_func ("/action/overlap2", test_overlap2);
g_test_add_func ("/action/introspection", test_introspection); g_test_add_func ("/action/introspection", test_introspection);
g_test_add_func ("/action/enabled", test_enabled); g_test_add_func ("/action/enabled", test_enabled);
g_test_add_func ("/action/reparenting", test_reparenting);
return g_test_run(); return g_test_run();
} }

View File

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