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];
|
GdkWindow *window = [[self contentView] gdkWindow];
|
||||||
GdkEvent *event;
|
GdkEvent *event;
|
||||||
|
|
||||||
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
|
|
||||||
gboolean maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
|
gboolean maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
|
||||||
|
|
||||||
/* In case the window is changed when maximized remove the maximized state */
|
/* In case the window is changed when maximized remove the maximized state */
|
||||||
@@ -209,7 +208,6 @@
|
|||||||
NSRect content_rect = [self contentRectForFrameRect:[self frame]];
|
NSRect content_rect = [self contentRectForFrameRect:[self frame]];
|
||||||
GdkWindow *window = [[self contentView] gdkWindow];
|
GdkWindow *window = [[self contentView] gdkWindow];
|
||||||
GdkEvent *event;
|
GdkEvent *event;
|
||||||
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
|
|
||||||
gboolean maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
|
gboolean maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
|
||||||
|
|
||||||
/* see same in windowDidMove */
|
/* see same in windowDidMove */
|
||||||
@@ -254,7 +252,7 @@
|
|||||||
screen:screen];
|
screen:screen];
|
||||||
|
|
||||||
[self setAcceptsMouseMovedEvents:YES];
|
[self setAcceptsMouseMovedEvents:YES];
|
||||||
[self setDelegate:self];
|
[self setDelegate:(id)self];
|
||||||
[self setReleasedWhenClosed:YES];
|
[self setReleasedWhenClosed:YES];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@@ -781,7 +779,6 @@ update_context_from_dragging_info (id <NSDraggingInfo> sender)
|
|||||||
{
|
{
|
||||||
NSRect screenFrame = [[self screen] visibleFrame];
|
NSRect screenFrame = [[self screen] visibleFrame];
|
||||||
GdkWindow *window = [[self contentView] gdkWindow];
|
GdkWindow *window = [[self contentView] gdkWindow];
|
||||||
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
|
|
||||||
gboolean maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
|
gboolean maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
|
||||||
|
|
||||||
if (!maximized)
|
if (!maximized)
|
||||||
@@ -795,7 +792,6 @@ update_context_from_dragging_info (id <NSDraggingInfo> sender)
|
|||||||
{
|
{
|
||||||
|
|
||||||
GdkWindow *window = [[self contentView] gdkWindow];
|
GdkWindow *window = [[self contentView] gdkWindow];
|
||||||
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
|
|
||||||
gboolean maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
|
gboolean maximized = gdk_window_get_state (window) & GDK_WINDOW_STATE_MAXIMIZED;
|
||||||
|
|
||||||
if (maximized)
|
if (maximized)
|
||||||
|
@@ -122,7 +122,6 @@
|
|||||||
-(void)unmarkText
|
-(void)unmarkText
|
||||||
{
|
{
|
||||||
GDK_NOTE (EVENTS, g_print ("unmarkText\n"));
|
GDK_NOTE (EVENTS, g_print ("unmarkText\n"));
|
||||||
gchar *prev_str;
|
|
||||||
markedRange = selectedRange = NSMakeRange (NSNotFound, 0);
|
markedRange = selectedRange = NSMakeRange (NSNotFound, 0);
|
||||||
|
|
||||||
g_object_set_data_full (G_OBJECT (gdk_window), TIC_MARKED_TEXT, NULL, g_free);
|
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"));
|
GDK_NOTE (EVENTS, g_print ("setMarkedText\n"));
|
||||||
const char *str;
|
const char *str;
|
||||||
gchar *prev_str;
|
|
||||||
|
|
||||||
if (replacementRange.location == NSNotFound)
|
if (replacementRange.location == NSNotFound)
|
||||||
{
|
{
|
||||||
@@ -182,7 +180,6 @@
|
|||||||
GDK_NOTE (EVENTS, g_print ("insertText\n"));
|
GDK_NOTE (EVENTS, g_print ("insertText\n"));
|
||||||
const char *str;
|
const char *str;
|
||||||
NSString *string;
|
NSString *string;
|
||||||
gchar *prev_str;
|
|
||||||
|
|
||||||
if ([self hasMarkedText])
|
if ([self hasMarkedText])
|
||||||
[self unmarkText];
|
[self unmarkText];
|
||||||
|
@@ -28,6 +28,8 @@ libgdk_quartz_la_SOURCES = \
|
|||||||
gdkdevicemanager-core-quartz.c \
|
gdkdevicemanager-core-quartz.c \
|
||||||
gdkdevicemanager-core-quartz.h \
|
gdkdevicemanager-core-quartz.h \
|
||||||
gdkdisplay-quartz.c \
|
gdkdisplay-quartz.c \
|
||||||
|
gdkdisplaylinksource.c \
|
||||||
|
gdkdisplaylinksource.h \
|
||||||
gdkdisplaymanager-quartz.c \
|
gdkdisplaymanager-quartz.c \
|
||||||
gdkdnd-quartz.c \
|
gdkdnd-quartz.c \
|
||||||
gdkdnd-quartz.h \
|
gdkdnd-quartz.h \
|
||||||
|
@@ -20,12 +20,14 @@
|
|||||||
|
|
||||||
#include <gdk/gdk.h>
|
#include <gdk/gdk.h>
|
||||||
#include <gdk/gdkdisplayprivate.h>
|
#include <gdk/gdkdisplayprivate.h>
|
||||||
|
#include <gdk/gdkframeclockprivate.h>
|
||||||
|
|
||||||
#include "gdkprivate-quartz.h"
|
#include "gdkprivate-quartz.h"
|
||||||
#include "gdkquartzscreen.h"
|
#include "gdkquartzscreen.h"
|
||||||
#include "gdkquartzwindow.h"
|
#include "gdkquartzwindow.h"
|
||||||
#include "gdkquartzdisplay.h"
|
#include "gdkquartzdisplay.h"
|
||||||
#include "gdkquartzdevicemanager-core.h"
|
#include "gdkquartzdevicemanager-core.h"
|
||||||
|
#include "gdkdisplaylinksource.h"
|
||||||
|
|
||||||
|
|
||||||
struct _GdkQuartzDisplay
|
struct _GdkQuartzDisplay
|
||||||
@@ -33,6 +35,11 @@ struct _GdkQuartzDisplay
|
|||||||
GdkDisplay display;
|
GdkDisplay display;
|
||||||
|
|
||||||
GList *input_devices;
|
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
|
struct _GdkQuartzDisplayClass
|
||||||
@@ -108,6 +115,112 @@ gdk_quartz_display_init_input (GdkDisplay *display)
|
|||||||
g_list_free (list);
|
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 *
|
GdkDisplay *
|
||||||
_gdk_quartz_display_open (const gchar *display_name)
|
_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_input (_gdk_display);
|
||||||
|
|
||||||
|
gdk_quartz_display_init_display_link (_gdk_display);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/* FIXME: Remove the #if 0 when we have these functions */
|
/* FIXME: Remove the #if 0 when we have these functions */
|
||||||
_gdk_quartz_dnd_init ();
|
_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_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);
|
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)
|
gdk_quartz_display_manager_class_init (GdkQuartzDisplayManagerClass *class)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||||
GdkDisplayManagerClass *manager_class = GDK_DISPLAY_MANAGER_CLASS (class);
|
|
||||||
|
|
||||||
object_class->finalize = gdk_quartz_display_manager_finalize;
|
object_class->finalize = gdk_quartz_display_manager_finalize;
|
||||||
}
|
}
|
||||||
|
@@ -404,7 +404,7 @@ get_window_point_from_screen_point (GdkWindow *window,
|
|||||||
static gboolean
|
static gboolean
|
||||||
is_mouse_button_press_event (NSEventType type)
|
is_mouse_button_press_event (NSEventType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch ((int)type)
|
||||||
{
|
{
|
||||||
case NSLeftMouseDown:
|
case NSLeftMouseDown:
|
||||||
case NSRightMouseDown:
|
case NSRightMouseDown:
|
||||||
@@ -895,7 +895,7 @@ fill_button_event (GdkWindow *window,
|
|||||||
state = get_keyboard_modifiers_from_ns_event (nsevent) |
|
state = get_keyboard_modifiers_from_ns_event (nsevent) |
|
||||||
_gdk_quartz_events_get_current_mouse_modifiers ();
|
_gdk_quartz_events_get_current_mouse_modifiers ();
|
||||||
|
|
||||||
switch ([nsevent type])
|
switch ((int)[nsevent type])
|
||||||
{
|
{
|
||||||
case NSLeftMouseDown:
|
case NSLeftMouseDown:
|
||||||
case NSRightMouseDown:
|
case NSRightMouseDown:
|
||||||
|
@@ -125,6 +125,12 @@ void _gdk_quartz_display_create_window_impl (GdkDisplay *display,
|
|||||||
GdkWindowAttr *attributes,
|
GdkWindowAttr *attributes,
|
||||||
gint attributes_mask);
|
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 */
|
/* Display methods - keymap */
|
||||||
GdkKeymap * _gdk_quartz_display_get_keymap (GdkDisplay *display);
|
GdkKeymap * _gdk_quartz_display_get_keymap (GdkDisplay *display);
|
||||||
|
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
#include <gdk/gdk.h>
|
#include <gdk/gdk.h>
|
||||||
#include <gdk/gdkdeviceprivate.h>
|
#include <gdk/gdkdeviceprivate.h>
|
||||||
#include <gdk/gdkdisplayprivate.h>
|
#include <gdk/gdkdisplayprivate.h>
|
||||||
|
#include <gdk/gdkframeclockprivate.h>
|
||||||
|
|
||||||
#include "gdkwindowimpl.h"
|
#include "gdkwindowimpl.h"
|
||||||
#include "gdkprivate-quartz.h"
|
#include "gdkprivate-quartz.h"
|
||||||
@@ -43,8 +44,6 @@ static gboolean in_process_all_updates = FALSE;
|
|||||||
|
|
||||||
static GSList *main_window_stack;
|
static GSList *main_window_stack;
|
||||||
|
|
||||||
void _gdk_quartz_window_flush (GdkWindowImplQuartz *window_impl);
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
gint x, y;
|
gint x, y;
|
||||||
@@ -154,7 +153,7 @@ gdk_window_impl_quartz_release_context (GdkWindowImplQuartz *window_impl,
|
|||||||
/* See comment in gdk_quartz_window_get_context(). */
|
/* See comment in gdk_quartz_window_get_context(). */
|
||||||
if (window_impl->in_paint_rect_count == 0)
|
if (window_impl->in_paint_rect_count == 0)
|
||||||
{
|
{
|
||||||
_gdk_quartz_window_flush (window_impl);
|
[window_impl->toplevel flushWindow];
|
||||||
[window_impl->view unlockFocus];
|
[window_impl->view unlockFocus];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -218,47 +217,6 @@ gdk_window_impl_quartz_finalize (GObject *object)
|
|||||||
G_OBJECT_CLASS (parent_class)->finalize (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;
|
static cairo_user_data_key_t gdk_quartz_cairo_key;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -418,7 +376,6 @@ _gdk_quartz_display_before_process_all_updates (GdkDisplay *display)
|
|||||||
void
|
void
|
||||||
_gdk_quartz_display_after_process_all_updates (GdkDisplay *display)
|
_gdk_quartz_display_after_process_all_updates (GdkDisplay *display)
|
||||||
{
|
{
|
||||||
GSList *old_update_nswindows = update_nswindows;
|
|
||||||
GSList *tmp_list = update_nswindows;
|
GSList *tmp_list = update_nswindows;
|
||||||
|
|
||||||
update_nswindows = NULL;
|
update_nswindows = NULL;
|
||||||
@@ -429,17 +386,13 @@ _gdk_quartz_display_after_process_all_updates (GdkDisplay *display)
|
|||||||
|
|
||||||
[[nswindow contentView] displayIfNeeded];
|
[[nswindow contentView] displayIfNeeded];
|
||||||
|
|
||||||
_gdk_quartz_window_flush (NULL);
|
|
||||||
|
|
||||||
[nswindow enableFlushWindow];
|
[nswindow enableFlushWindow];
|
||||||
[nswindow flushWindow];
|
[nswindow flushWindow];
|
||||||
[nswindow release];
|
[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;
|
in_process_all_updates = FALSE;
|
||||||
|
|
||||||
NSEnableScreenUpdates ();
|
NSEnableScreenUpdates ();
|
||||||
@@ -776,6 +729,29 @@ get_nsscreen_for_point (gint x, gint y)
|
|||||||
return screen;
|
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
|
void
|
||||||
_gdk_quartz_display_create_window_impl (GdkDisplay *display,
|
_gdk_quartz_display_create_window_impl (GdkDisplay *display,
|
||||||
GdkWindow *window,
|
GdkWindow *window,
|
||||||
@@ -787,6 +763,7 @@ _gdk_quartz_display_create_window_impl (GdkDisplay *display,
|
|||||||
{
|
{
|
||||||
GdkWindowImplQuartz *impl;
|
GdkWindowImplQuartz *impl;
|
||||||
GdkWindowImplQuartz *parent_impl;
|
GdkWindowImplQuartz *parent_impl;
|
||||||
|
GdkFrameClock *frame_clock;
|
||||||
|
|
||||||
GDK_QUARTZ_ALLOC_POOL;
|
GDK_QUARTZ_ALLOC_POOL;
|
||||||
|
|
||||||
@@ -921,6 +898,13 @@ _gdk_quartz_display_create_window_impl (GdkDisplay *display,
|
|||||||
|
|
||||||
if (attributes_mask & GDK_WA_TYPE_HINT)
|
if (attributes_mask & GDK_WA_TYPE_HINT)
|
||||||
gdk_window_set_type_hint (window, attributes->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
|
void
|
||||||
@@ -976,9 +960,14 @@ gdk_quartz_window_destroy (GdkWindow *window,
|
|||||||
{
|
{
|
||||||
GdkWindowImplQuartz *impl;
|
GdkWindowImplQuartz *impl;
|
||||||
GdkWindow *parent;
|
GdkWindow *parent;
|
||||||
|
GdkDisplay *display;
|
||||||
|
|
||||||
impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
|
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);
|
main_window_stack = g_slist_remove (main_window_stack, window);
|
||||||
|
|
||||||
g_list_free (impl->sorted_children);
|
g_list_free (impl->sorted_children);
|
||||||
@@ -3025,21 +3014,25 @@ static CGContextRef
|
|||||||
gdk_root_window_impl_quartz_get_context (GdkWindowImplQuartz *window,
|
gdk_root_window_impl_quartz_get_context (GdkWindowImplQuartz *window,
|
||||||
gboolean antialias)
|
gboolean antialias)
|
||||||
{
|
{
|
||||||
CGColorSpaceRef colorspace;
|
CGColorSpaceRef colorSpace;
|
||||||
CGContextRef cg_context;
|
CGContextRef cg_context;
|
||||||
GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (window);
|
GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (window);
|
||||||
|
|
||||||
if (GDK_WINDOW_DESTROYED (window_impl->wrapper))
|
if (GDK_WINDOW_DESTROYED (window_impl->wrapper))
|
||||||
return NULL;
|
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
|
/* 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.
|
* by creating a 1x1 bitmap and return a context to that.
|
||||||
*/
|
*/
|
||||||
colorspace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
|
|
||||||
cg_context = CGBitmapContextCreate (NULL,
|
cg_context = CGBitmapContextCreate (NULL,
|
||||||
1, 1, 8, 4, colorspace,
|
1, 1, 8, 4, colorSpace,
|
||||||
kCGImageAlphaPremultipliedLast);
|
kCGBitmapByteOrder32Host|kCGImageAlphaPremultipliedLast);
|
||||||
CGColorSpaceRelease (colorspace);
|
|
||||||
|
CGColorSpaceRelease (colorSpace);
|
||||||
|
|
||||||
return cg_context;
|
return cg_context;
|
||||||
}
|
}
|
||||||
|
@@ -64,6 +64,9 @@ struct _GdkWindowImplQuartz
|
|||||||
gint shadow_top;
|
gint shadow_top;
|
||||||
|
|
||||||
gint shadow_max;
|
gint shadow_max;
|
||||||
|
|
||||||
|
GList frame_link;
|
||||||
|
gint pending_frame_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GdkWindowImplQuartzClass
|
struct _GdkWindowImplQuartzClass
|
||||||
|
@@ -18,9 +18,15 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "gtkdebug.h"
|
#include "gtkdebug.h"
|
||||||
|
#include "gtkstylecontextprivate.h"
|
||||||
#include "gtkpixelcacheprivate.h"
|
#include "gtkpixelcacheprivate.h"
|
||||||
#include "gtkstylecontextprivate.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
|
#define BLOW_CACHE_TIMEOUT_SEC 20
|
||||||
|
|
||||||
/* The extra size of the offscreen surface we allocate
|
/* The extra size of the offscreen surface we allocate
|
||||||
@@ -243,6 +249,18 @@ _gtk_pixel_cache_create_surface_if_needed (GtkPixelCache *cache,
|
|||||||
cache->surface =
|
cache->surface =
|
||||||
gdk_window_create_similar_surface (window, content,
|
gdk_window_create_similar_surface (window, content,
|
||||||
surface_w, surface_h);
|
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.x = 0;
|
||||||
rect.y = 0;
|
rect.y = 0;
|
||||||
rect.width = surface_w;
|
rect.width = surface_w;
|
||||||
|
Reference in New Issue
Block a user