Compare commits
8 Commits
css-variab
...
wip/cherge
Author | SHA1 | Date | |
---|---|---|---|
|
67aef5f542 | ||
|
b1be2a70fd | ||
|
abe99e4611 | ||
|
f7b7c33cc9 | ||
|
519e5a94d2 | ||
|
7e1db6cf64 | ||
|
f9395b52f7 | ||
|
01e633a763 |
@@ -178,7 +178,6 @@
|
||||
GdkWindow *window = [[self contentView] gdkWindow];
|
||||
GdkEvent *event;
|
||||
|
||||
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
|
||||
gboolean maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
|
||||
|
||||
/* In case the window is changed when maximized remove the maximized state */
|
||||
@@ -209,7 +208,6 @@
|
||||
NSRect content_rect = [self contentRectForFrameRect:[self frame]];
|
||||
GdkWindow *window = [[self contentView] gdkWindow];
|
||||
GdkEvent *event;
|
||||
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
|
||||
gboolean maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
|
||||
|
||||
/* see same in windowDidMove */
|
||||
@@ -254,7 +252,7 @@
|
||||
screen:screen];
|
||||
|
||||
[self setAcceptsMouseMovedEvents:YES];
|
||||
[self setDelegate:self];
|
||||
[self setDelegate:(id)self];
|
||||
[self setReleasedWhenClosed:YES];
|
||||
|
||||
return self;
|
||||
@@ -781,7 +779,6 @@ update_context_from_dragging_info (id <NSDraggingInfo> sender)
|
||||
{
|
||||
NSRect screenFrame = [[self screen] visibleFrame];
|
||||
GdkWindow *window = [[self contentView] gdkWindow];
|
||||
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
|
||||
gboolean maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
|
||||
|
||||
if (!maximized)
|
||||
@@ -795,7 +792,6 @@ update_context_from_dragging_info (id <NSDraggingInfo> sender)
|
||||
{
|
||||
|
||||
GdkWindow *window = [[self contentView] gdkWindow];
|
||||
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
|
||||
gboolean maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
|
||||
|
||||
if (maximized)
|
||||
|
@@ -122,7 +122,6 @@
|
||||
-(void)unmarkText
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_print ("unmarkText\n"));
|
||||
gchar *prev_str;
|
||||
markedRange = selectedRange = NSMakeRange (NSNotFound, 0);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (gdk_window), TIC_MARKED_TEXT, NULL, g_free);
|
||||
@@ -132,7 +131,6 @@
|
||||
{
|
||||
GDK_NOTE (EVENTS, g_print ("setMarkedText\n"));
|
||||
const char *str;
|
||||
gchar *prev_str;
|
||||
|
||||
if (replacementRange.location == NSNotFound)
|
||||
{
|
||||
@@ -182,7 +180,6 @@
|
||||
GDK_NOTE (EVENTS, g_print ("insertText\n"));
|
||||
const char *str;
|
||||
NSString *string;
|
||||
gchar *prev_str;
|
||||
|
||||
if ([self hasMarkedText])
|
||||
[self unmarkText];
|
||||
|
@@ -28,6 +28,8 @@ libgdk_quartz_la_SOURCES = \
|
||||
gdkdevicemanager-core-quartz.c \
|
||||
gdkdevicemanager-core-quartz.h \
|
||||
gdkdisplay-quartz.c \
|
||||
gdkdisplaylinksource.c \
|
||||
gdkdisplaylinksource.h \
|
||||
gdkdisplaymanager-quartz.c \
|
||||
gdkdnd-quartz.c \
|
||||
gdkdnd-quartz.h \
|
||||
|
@@ -20,12 +20,14 @@
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkdisplayprivate.h>
|
||||
#include <gdk/gdkframeclockprivate.h>
|
||||
|
||||
#include "gdkprivate-quartz.h"
|
||||
#include "gdkquartzscreen.h"
|
||||
#include "gdkquartzwindow.h"
|
||||
#include "gdkquartzdisplay.h"
|
||||
#include "gdkquartzdevicemanager-core.h"
|
||||
#include "gdkdisplaylinksource.h"
|
||||
|
||||
|
||||
struct _GdkQuartzDisplay
|
||||
@@ -33,6 +35,11 @@ struct _GdkQuartzDisplay
|
||||
GdkDisplay display;
|
||||
|
||||
GList *input_devices;
|
||||
|
||||
/* This structure is not allocated. It points to an embedded
|
||||
* GList in the GdkWindow. */
|
||||
GList *windows_awaiting_frame;
|
||||
GSource *frame_source;
|
||||
};
|
||||
|
||||
struct _GdkQuartzDisplayClass
|
||||
@@ -108,6 +115,112 @@ gdk_quartz_display_init_input (GdkDisplay *display)
|
||||
g_list_free (list);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_quartz_display_add_frame_callback (GdkDisplay *display,
|
||||
GdkWindow *window)
|
||||
{
|
||||
GdkQuartzDisplay *display_quartz;
|
||||
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window);
|
||||
|
||||
display_quartz = GDK_QUARTZ_DISPLAY (display);
|
||||
|
||||
impl->frame_link.data = window;
|
||||
impl->frame_link.prev = NULL;
|
||||
impl->frame_link.next = display_quartz->windows_awaiting_frame;
|
||||
|
||||
display_quartz->windows_awaiting_frame = &impl->frame_link;
|
||||
|
||||
if (impl->frame_link.next == NULL)
|
||||
gdk_display_link_source_unpause ((GdkDisplayLinkSource *)display_quartz->frame_source);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_quartz_display_remove_frame_callback (GdkDisplay *display,
|
||||
GdkWindow *window)
|
||||
{
|
||||
GdkQuartzDisplay *display_quartz = GDK_QUARTZ_DISPLAY (display);
|
||||
GList *link;
|
||||
|
||||
link = g_list_find (display_quartz->windows_awaiting_frame, window);
|
||||
|
||||
if (link != NULL)
|
||||
{
|
||||
display_quartz->windows_awaiting_frame =
|
||||
g_list_remove_link (display_quartz->windows_awaiting_frame, link);
|
||||
}
|
||||
|
||||
if (display_quartz->windows_awaiting_frame == NULL)
|
||||
gdk_display_link_source_pause ((GdkDisplayLinkSource *)display_quartz->frame_source);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_quartz_display_frame_cb (gpointer data)
|
||||
{
|
||||
GdkDisplayLinkSource *source;
|
||||
GdkQuartzDisplay *display_quartz = data;
|
||||
GList *iter;
|
||||
gint64 presentation_time;
|
||||
gint64 now;
|
||||
|
||||
source = (GdkDisplayLinkSource *)display_quartz->frame_source;
|
||||
|
||||
iter = display_quartz->windows_awaiting_frame;
|
||||
display_quartz->windows_awaiting_frame = NULL;
|
||||
|
||||
if (iter == NULL)
|
||||
{
|
||||
gdk_display_link_source_pause (source);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
presentation_time = source->presentation_time;
|
||||
now = g_source_get_time (display_quartz->frame_source);
|
||||
|
||||
for (; iter != NULL; iter = iter->next)
|
||||
{
|
||||
GdkWindow *window = iter->data;
|
||||
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
|
||||
GdkFrameClock *frame_clock = gdk_window_get_frame_clock (window);
|
||||
GdkFrameTimings *timings;
|
||||
|
||||
if (frame_clock == NULL)
|
||||
continue;
|
||||
|
||||
_gdk_frame_clock_thaw (frame_clock);
|
||||
|
||||
if (impl->pending_frame_counter)
|
||||
{
|
||||
timings = gdk_frame_clock_get_timings (frame_clock, impl->pending_frame_counter);
|
||||
if (timings != NULL)
|
||||
timings->presentation_time = presentation_time - source->refresh_interval;
|
||||
impl->pending_frame_counter = 0;
|
||||
}
|
||||
|
||||
timings = gdk_frame_clock_get_current_timings (frame_clock);
|
||||
|
||||
if (timings != NULL)
|
||||
{
|
||||
timings->refresh_interval = source->refresh_interval;
|
||||
timings->predicted_presentation_time = source->presentation_time;
|
||||
}
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_quartz_display_init_display_link (GdkDisplay *display)
|
||||
{
|
||||
GdkQuartzDisplay *display_quartz = GDK_QUARTZ_DISPLAY (display);
|
||||
|
||||
display_quartz->frame_source = gdk_display_link_source_new ();
|
||||
g_source_set_callback (display_quartz->frame_source,
|
||||
gdk_quartz_display_frame_cb,
|
||||
display,
|
||||
NULL);
|
||||
g_source_attach (display_quartz->frame_source, NULL);
|
||||
}
|
||||
|
||||
GdkDisplay *
|
||||
_gdk_quartz_display_open (const gchar *display_name)
|
||||
{
|
||||
@@ -129,6 +242,8 @@ _gdk_quartz_display_open (const gchar *display_name)
|
||||
|
||||
gdk_quartz_display_init_input (_gdk_display);
|
||||
|
||||
gdk_quartz_display_init_display_link (_gdk_display);
|
||||
|
||||
#if 0
|
||||
/* FIXME: Remove the #if 0 when we have these functions */
|
||||
_gdk_quartz_dnd_init ();
|
||||
@@ -284,6 +399,9 @@ gdk_quartz_display_finalize (GObject *object)
|
||||
|
||||
g_list_free_full (display_quartz->input_devices, g_object_unref);
|
||||
|
||||
g_source_unref (display_quartz->frame_source);
|
||||
display_quartz->windows_awaiting_frame = NULL;
|
||||
|
||||
G_OBJECT_CLASS (gdk_quartz_display_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
251
gdk/quartz/gdkdisplaylinksource.c
Normal file
251
gdk/quartz/gdkdisplaylinksource.c
Normal file
@@ -0,0 +1,251 @@
|
||||
/* gdkdisplaylinksource.c
|
||||
*
|
||||
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Christian Hergert <christian@hergert.me>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
#include "gdkprivate-quartz.h"
|
||||
#include "gdkdisplaylinksource.h"
|
||||
|
||||
static gint64 host_to_frame_clock_time (gint64 host_time);
|
||||
|
||||
static gboolean
|
||||
gdk_display_link_source_prepare (GSource *source,
|
||||
gint *timeout_)
|
||||
{
|
||||
GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
|
||||
gint64 now;
|
||||
|
||||
now = g_source_get_time (source);
|
||||
|
||||
if (now < impl->presentation_time)
|
||||
*timeout_ = (impl->presentation_time - now) / 1000L;
|
||||
else
|
||||
*timeout_ = -1;
|
||||
|
||||
return impl->needs_dispatch;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_display_link_source_check (GSource *source)
|
||||
{
|
||||
GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
|
||||
return impl->needs_dispatch;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_display_link_source_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
|
||||
gboolean ret = G_SOURCE_CONTINUE;
|
||||
|
||||
impl->needs_dispatch = FALSE;
|
||||
|
||||
if (callback != NULL)
|
||||
ret = callback (user_data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_display_link_source_finalize (GSource *source)
|
||||
{
|
||||
GdkDisplayLinkSource *impl = (GdkDisplayLinkSource *)source;
|
||||
|
||||
CVDisplayLinkStop (impl->display_link);
|
||||
CVDisplayLinkRelease (impl->display_link);
|
||||
}
|
||||
|
||||
static GSourceFuncs gdk_display_link_source_funcs = {
|
||||
gdk_display_link_source_prepare,
|
||||
gdk_display_link_source_check,
|
||||
gdk_display_link_source_dispatch,
|
||||
gdk_display_link_source_finalize
|
||||
};
|
||||
|
||||
void
|
||||
gdk_display_link_source_pause (GdkDisplayLinkSource *source)
|
||||
{
|
||||
CVDisplayLinkStop (source->display_link);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_display_link_source_unpause (GdkDisplayLinkSource *source)
|
||||
{
|
||||
CVDisplayLinkStart (source->display_link);
|
||||
}
|
||||
|
||||
static CVReturn
|
||||
gdk_display_link_source_frame_cb (CVDisplayLinkRef display_link,
|
||||
const CVTimeStamp *inNow,
|
||||
const CVTimeStamp *inOutputTime,
|
||||
CVOptionFlags flagsIn,
|
||||
CVOptionFlags *flagsOut,
|
||||
void *user_data)
|
||||
{
|
||||
GdkDisplayLinkSource *impl = user_data;
|
||||
gint64 presentation_time;
|
||||
gboolean needs_wakeup;
|
||||
|
||||
needs_wakeup = !g_atomic_int_get (&impl->needs_dispatch);
|
||||
|
||||
presentation_time = host_to_frame_clock_time (inOutputTime->hostTime);
|
||||
|
||||
impl->presentation_time = presentation_time;
|
||||
impl->needs_dispatch = TRUE;
|
||||
|
||||
if (needs_wakeup)
|
||||
{
|
||||
NSEvent *event;
|
||||
|
||||
/* Post a message so we'll break out of the message loop.
|
||||
*
|
||||
* We don't use g_main_context_wakeup() here because that
|
||||
* would result in sending a message to the pipe(2) fd in
|
||||
* the select thread which would then send this message as
|
||||
* well. Lots of extra work.
|
||||
*/
|
||||
event = [NSEvent otherEventWithType: NSApplicationDefined
|
||||
location: NSZeroPoint
|
||||
modifierFlags: 0
|
||||
timestamp: 0
|
||||
windowNumber: 0
|
||||
context: nil
|
||||
subtype: GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP
|
||||
data1: 0
|
||||
data2: 0];
|
||||
|
||||
[NSApp postEvent:event atStart:YES];
|
||||
}
|
||||
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_display_link_source_new:
|
||||
*
|
||||
* Creates a new #GSource that will activate the dispatch function upon
|
||||
* notification from a CVDisplayLink that a new frame should be drawn.
|
||||
*
|
||||
* Effort is made to keep the transition from the high-priority
|
||||
* CVDisplayLink thread into this GSource lightweight. However, this is
|
||||
* somewhat non-ideal since the best case would be to do the drawing
|
||||
* from the high-priority thread.
|
||||
*
|
||||
* Returns: (transfer full): A newly created #GSource.
|
||||
*/
|
||||
GSource *
|
||||
gdk_display_link_source_new (void)
|
||||
{
|
||||
GdkDisplayLinkSource *impl;
|
||||
GSource *source;
|
||||
CVReturn ret;
|
||||
double period;
|
||||
|
||||
source = g_source_new (&gdk_display_link_source_funcs, sizeof *impl);
|
||||
impl = (GdkDisplayLinkSource *)source;
|
||||
|
||||
/*
|
||||
* Create our link based on currently connected displays.
|
||||
* If there are multiple displays, this will be something that tries
|
||||
* to work for all of them. In the future, we may want to explore multiple
|
||||
* links based on the connected displays.
|
||||
*/
|
||||
ret = CVDisplayLinkCreateWithActiveCGDisplays (&impl->display_link);
|
||||
if (ret != kCVReturnSuccess)
|
||||
{
|
||||
g_warning ("Failed to initialize CVDisplayLink!");
|
||||
return source;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine our nominal period between frames.
|
||||
*/
|
||||
period = CVDisplayLinkGetActualOutputVideoRefreshPeriod (impl->display_link);
|
||||
if (period == 0.0)
|
||||
period = 1.0 / 60.0;
|
||||
impl->refresh_interval = period * 1000000L;
|
||||
|
||||
/*
|
||||
* Wire up our callback to be executed within the high-priority thread.
|
||||
*/
|
||||
CVDisplayLinkSetOutputCallback (impl->display_link,
|
||||
gdk_display_link_source_frame_cb,
|
||||
source);
|
||||
|
||||
g_source_set_name (source, "[gdk] quartz frame clock");
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
static gint64
|
||||
host_to_frame_clock_time (gint64 host_time)
|
||||
{
|
||||
static mach_timebase_info_data_t timebase_info;
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
*
|
||||
* This code is taken from GLib to match g_get_monotonic_time().
|
||||
*/
|
||||
if (G_UNLIKELY (timebase_info.denom == 0))
|
||||
{
|
||||
/* This is a fraction that we must use to scale
|
||||
* mach_absolute_time() by in order to reach nanoseconds.
|
||||
*
|
||||
* We've only ever observed this to be 1/1, but maybe it could be
|
||||
* 1000/1 if mach time is microseconds already, or 1/1000 if
|
||||
* picoseconds. Try to deal nicely with that.
|
||||
*/
|
||||
mach_timebase_info (&timebase_info);
|
||||
|
||||
/* We actually want microseconds... */
|
||||
if (timebase_info.numer % 1000 == 0)
|
||||
timebase_info.numer /= 1000;
|
||||
else
|
||||
timebase_info.denom *= 1000;
|
||||
|
||||
/* We want to make the numer 1 to avoid having to multiply... */
|
||||
if (timebase_info.denom % timebase_info.numer == 0)
|
||||
{
|
||||
timebase_info.denom /= timebase_info.numer;
|
||||
timebase_info.numer = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We could just multiply by timebase_info.numer below, but why
|
||||
* bother for a case that may never actually exist...
|
||||
*
|
||||
* Plus -- performing the multiplication would risk integer
|
||||
* overflow. If we ever actually end up in this situation, we
|
||||
* should more carefully evaluate the correct course of action.
|
||||
*/
|
||||
mach_timebase_info (&timebase_info); /* Get a fresh copy for a better message */
|
||||
g_error ("Got weird mach timebase info of %d/%d. Please file a bug against GLib.",
|
||||
timebase_info.numer, timebase_info.denom);
|
||||
}
|
||||
}
|
||||
|
||||
return host_time / timebase_info.denom;
|
||||
}
|
48
gdk/quartz/gdkdisplaylinksource.h
Normal file
48
gdk/quartz/gdkdisplaylinksource.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* gdkdisplaylinksource.h
|
||||
*
|
||||
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Christian Hergert <christian@hergert.me>
|
||||
*/
|
||||
|
||||
#ifndef GDK_DISPLAY_LINK_SOURCE_H
|
||||
#define GDK_DISPLAY_LINK_SOURCE_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <QuartzCore/QuartzCore.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GSource source;
|
||||
|
||||
CVDisplayLinkRef display_link;
|
||||
gint64 refresh_interval;
|
||||
|
||||
volatile gint64 presentation_time;
|
||||
volatile guint needs_dispatch;
|
||||
} GdkDisplayLinkSource;
|
||||
|
||||
GSource *gdk_display_link_source_new (void);
|
||||
void gdk_display_link_source_pause (GdkDisplayLinkSource *source);
|
||||
void gdk_display_link_source_unpause (GdkDisplayLinkSource *source);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GDK_DISPLAY_LINK_SOURCE_H */
|
@@ -55,7 +55,6 @@ static void
|
||||
gdk_quartz_display_manager_class_init (GdkQuartzDisplayManagerClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GdkDisplayManagerClass *manager_class = GDK_DISPLAY_MANAGER_CLASS (class);
|
||||
|
||||
object_class->finalize = gdk_quartz_display_manager_finalize;
|
||||
}
|
||||
|
@@ -404,7 +404,7 @@ get_window_point_from_screen_point (GdkWindow *window,
|
||||
static gboolean
|
||||
is_mouse_button_press_event (NSEventType type)
|
||||
{
|
||||
switch (type)
|
||||
switch ((int)type)
|
||||
{
|
||||
case NSLeftMouseDown:
|
||||
case NSRightMouseDown:
|
||||
@@ -895,7 +895,7 @@ fill_button_event (GdkWindow *window,
|
||||
state = get_keyboard_modifiers_from_ns_event (nsevent) |
|
||||
_gdk_quartz_events_get_current_mouse_modifiers ();
|
||||
|
||||
switch ([nsevent type])
|
||||
switch ((int)[nsevent type])
|
||||
{
|
||||
case NSLeftMouseDown:
|
||||
case NSRightMouseDown:
|
||||
|
@@ -125,6 +125,12 @@ void _gdk_quartz_display_create_window_impl (GdkDisplay *display,
|
||||
GdkWindowAttr *attributes,
|
||||
gint attributes_mask);
|
||||
|
||||
/* Display methods - frame clock */
|
||||
void _gdk_quartz_display_add_frame_callback (GdkDisplay *display,
|
||||
GdkWindow *window);
|
||||
void _gdk_quartz_display_remove_frame_callback (GdkDisplay *display,
|
||||
GdkWindow *window);
|
||||
|
||||
/* Display methods - keymap */
|
||||
GdkKeymap * _gdk_quartz_display_get_keymap (GdkDisplay *display);
|
||||
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkdeviceprivate.h>
|
||||
#include <gdk/gdkdisplayprivate.h>
|
||||
#include <gdk/gdkframeclockprivate.h>
|
||||
|
||||
#include "gdkwindowimpl.h"
|
||||
#include "gdkprivate-quartz.h"
|
||||
@@ -43,8 +44,6 @@ static gboolean in_process_all_updates = FALSE;
|
||||
|
||||
static GSList *main_window_stack;
|
||||
|
||||
void _gdk_quartz_window_flush (GdkWindowImplQuartz *window_impl);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gint x, y;
|
||||
@@ -154,7 +153,7 @@ gdk_window_impl_quartz_release_context (GdkWindowImplQuartz *window_impl,
|
||||
/* See comment in gdk_quartz_window_get_context(). */
|
||||
if (window_impl->in_paint_rect_count == 0)
|
||||
{
|
||||
_gdk_quartz_window_flush (window_impl);
|
||||
[window_impl->toplevel flushWindow];
|
||||
[window_impl->view unlockFocus];
|
||||
}
|
||||
}
|
||||
@@ -218,47 +217,6 @@ gdk_window_impl_quartz_finalize (GObject *object)
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
/* Help preventing "beam sync penalty" where CG makes all graphics code
|
||||
* block until the next vsync if we try to flush (including call display on
|
||||
* a view) too often. We do this by limiting the manual flushing done
|
||||
* outside of expose calls to less than some frequency when measured over
|
||||
* the last 4 flushes. This is a bit arbitray, but seems to make it possible
|
||||
* for some quick manual flushes (such as gtkruler or gimp’s marching ants)
|
||||
* without hitting the max flush frequency.
|
||||
*
|
||||
* If drawable NULL, no flushing is done, only registering that a flush was
|
||||
* done externally.
|
||||
*/
|
||||
void
|
||||
_gdk_quartz_window_flush (GdkWindowImplQuartz *window_impl)
|
||||
{
|
||||
static struct timeval prev_tv;
|
||||
static gint intervals[4];
|
||||
static gint index;
|
||||
struct timeval tv;
|
||||
gint ms;
|
||||
|
||||
gettimeofday (&tv, NULL);
|
||||
ms = (tv.tv_sec - prev_tv.tv_sec) * 1000 + (tv.tv_usec - prev_tv.tv_usec) / 1000;
|
||||
intervals[index++ % 4] = ms;
|
||||
|
||||
if (window_impl)
|
||||
{
|
||||
ms = intervals[0] + intervals[1] + intervals[2] + intervals[3];
|
||||
|
||||
/* ~25Hz on average. */
|
||||
if (ms > 4*40)
|
||||
{
|
||||
if (window_impl)
|
||||
[window_impl->toplevel flushWindow];
|
||||
|
||||
prev_tv = tv;
|
||||
}
|
||||
}
|
||||
else
|
||||
prev_tv = tv;
|
||||
}
|
||||
|
||||
static cairo_user_data_key_t gdk_quartz_cairo_key;
|
||||
|
||||
typedef struct {
|
||||
@@ -418,7 +376,6 @@ _gdk_quartz_display_before_process_all_updates (GdkDisplay *display)
|
||||
void
|
||||
_gdk_quartz_display_after_process_all_updates (GdkDisplay *display)
|
||||
{
|
||||
GSList *old_update_nswindows = update_nswindows;
|
||||
GSList *tmp_list = update_nswindows;
|
||||
|
||||
update_nswindows = NULL;
|
||||
@@ -429,17 +386,13 @@ _gdk_quartz_display_after_process_all_updates (GdkDisplay *display)
|
||||
|
||||
[[nswindow contentView] displayIfNeeded];
|
||||
|
||||
_gdk_quartz_window_flush (NULL);
|
||||
|
||||
[nswindow enableFlushWindow];
|
||||
[nswindow flushWindow];
|
||||
[nswindow release];
|
||||
|
||||
tmp_list = tmp_list->next;
|
||||
tmp_list = g_slist_remove_link (tmp_list, tmp_list);
|
||||
}
|
||||
|
||||
g_slist_free (old_update_nswindows);
|
||||
|
||||
in_process_all_updates = FALSE;
|
||||
|
||||
NSEnableScreenUpdates ();
|
||||
@@ -776,6 +729,29 @@ get_nsscreen_for_point (gint x, gint y)
|
||||
return screen;
|
||||
}
|
||||
|
||||
static void
|
||||
on_frame_clock_before_paint (GdkFrameClock *frame_clock,
|
||||
GdkWindow *window)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
on_frame_clock_after_paint (GdkFrameClock *frame_clock,
|
||||
GdkWindow *window)
|
||||
{
|
||||
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
|
||||
GdkDisplay *display = gdk_window_get_display (window);
|
||||
GdkFrameTimings *timings;
|
||||
|
||||
timings = gdk_frame_clock_get_current_timings (frame_clock);
|
||||
if (timings != NULL)
|
||||
impl->pending_frame_counter = timings->frame_counter;
|
||||
|
||||
_gdk_quartz_display_add_frame_callback (display, window);
|
||||
|
||||
_gdk_frame_clock_freeze (frame_clock);
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_quartz_display_create_window_impl (GdkDisplay *display,
|
||||
GdkWindow *window,
|
||||
@@ -787,6 +763,7 @@ _gdk_quartz_display_create_window_impl (GdkDisplay *display,
|
||||
{
|
||||
GdkWindowImplQuartz *impl;
|
||||
GdkWindowImplQuartz *parent_impl;
|
||||
GdkFrameClock *frame_clock;
|
||||
|
||||
GDK_QUARTZ_ALLOC_POOL;
|
||||
|
||||
@@ -921,6 +898,13 @@ _gdk_quartz_display_create_window_impl (GdkDisplay *display,
|
||||
|
||||
if (attributes_mask & GDK_WA_TYPE_HINT)
|
||||
gdk_window_set_type_hint (window, attributes->type_hint);
|
||||
|
||||
frame_clock = gdk_window_get_frame_clock (window);
|
||||
|
||||
g_signal_connect (frame_clock, "before-paint",
|
||||
G_CALLBACK (on_frame_clock_before_paint), window);
|
||||
g_signal_connect (frame_clock, "after-paint",
|
||||
G_CALLBACK (on_frame_clock_after_paint), window);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -976,9 +960,14 @@ gdk_quartz_window_destroy (GdkWindow *window,
|
||||
{
|
||||
GdkWindowImplQuartz *impl;
|
||||
GdkWindow *parent;
|
||||
GdkDisplay *display;
|
||||
|
||||
impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
|
||||
|
||||
display = gdk_window_get_display (window);
|
||||
|
||||
_gdk_quartz_display_remove_frame_callback (display, window);
|
||||
|
||||
main_window_stack = g_slist_remove (main_window_stack, window);
|
||||
|
||||
g_list_free (impl->sorted_children);
|
||||
@@ -3025,21 +3014,25 @@ static CGContextRef
|
||||
gdk_root_window_impl_quartz_get_context (GdkWindowImplQuartz *window,
|
||||
gboolean antialias)
|
||||
{
|
||||
CGColorSpaceRef colorspace;
|
||||
CGColorSpaceRef colorSpace;
|
||||
CGContextRef cg_context;
|
||||
GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (window);
|
||||
|
||||
if (GDK_WINDOW_DESTROYED (window_impl->wrapper))
|
||||
return NULL;
|
||||
|
||||
colorSpace = CGDisplayCopyColorSpace (CGMainDisplayID ());
|
||||
if (!colorSpace)
|
||||
colorSpace = CGColorSpaceCreateDeviceRGB ();
|
||||
|
||||
/* We do not have the notion of a root window on OS X. We fake this
|
||||
* by creating a 1x1 bitmap and return a context to that.
|
||||
*/
|
||||
colorspace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
|
||||
cg_context = CGBitmapContextCreate (NULL,
|
||||
1, 1, 8, 4, colorspace,
|
||||
kCGImageAlphaPremultipliedLast);
|
||||
CGColorSpaceRelease (colorspace);
|
||||
1, 1, 8, 4, colorSpace,
|
||||
kCGBitmapByteOrder32Host|kCGImageAlphaPremultipliedLast);
|
||||
|
||||
CGColorSpaceRelease (colorSpace);
|
||||
|
||||
return cg_context;
|
||||
}
|
||||
|
@@ -64,6 +64,9 @@ struct _GdkWindowImplQuartz
|
||||
gint shadow_top;
|
||||
|
||||
gint shadow_max;
|
||||
|
||||
GList frame_link;
|
||||
gint pending_frame_counter;
|
||||
};
|
||||
|
||||
struct _GdkWindowImplQuartzClass
|
||||
|
@@ -18,9 +18,15 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkdebug.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkpixelcacheprivate.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
|
||||
#ifdef GDK_WINDOWING_QUARTZ
|
||||
# include <cairo/cairo-quartz.h>
|
||||
# include <gdk/quartz/gdkquartz.h>
|
||||
#endif
|
||||
|
||||
#define BLOW_CACHE_TIMEOUT_SEC 20
|
||||
|
||||
/* The extra size of the offscreen surface we allocate
|
||||
@@ -243,6 +249,18 @@ _gtk_pixel_cache_create_surface_if_needed (GtkPixelCache *cache,
|
||||
cache->surface =
|
||||
gdk_window_create_similar_surface (window, content,
|
||||
surface_w, surface_h);
|
||||
|
||||
#ifdef GDK_WINDOWING_QUARTZ
|
||||
if (GDK_IS_QUARTZ_WINDOW (window))
|
||||
{
|
||||
cairo_surface_t *base;
|
||||
|
||||
base = cache->surface;
|
||||
cache->surface = cairo_quartz_surface_create_cg_layer (base, content, surface_w, surface_h);
|
||||
cairo_surface_destroy (base);
|
||||
}
|
||||
#endif
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = surface_w;
|
||||
|
Reference in New Issue
Block a user