Merge branch 'wip/chergert/quartz4u' into 'master'

Merge GDK macOS branch

See merge request GNOME/gtk!2272
This commit is contained in:
Matthias Clasen 2020-07-21 22:22:41 +00:00
commit 2e07fcd680
104 changed files with 11830 additions and 10875 deletions

View File

@ -12,6 +12,7 @@ G_BEGIN_DECLS
#mesondefine GDK_WINDOWING_X11
#mesondefine GDK_WINDOWING_BROADWAY
#mesondefine GDK_WINDOWING_MACOS
#mesondefine GDK_WINDOWING_WAYLAND
#mesondefine GDK_WINDOWING_WIN32

View File

@ -875,7 +875,7 @@ init (void)
g_slist_free (formats);
#ifdef G_OS_UNIX
#if defined(G_OS_UNIX) && !defined(__APPLE__)
file_transfer_portal_register ();
#endif

View File

@ -907,7 +907,7 @@ init (void)
g_slist_free (formats);
#ifdef G_OS_UNIX
#if defined(G_OS_UNIX) && !defined(__APPLE__)
file_transfer_portal_register ();
#endif

View File

@ -50,6 +50,10 @@
#include "broadway/gdkprivate-broadway.h"
#endif
#ifdef GDK_WINDOWING_MACOS
#include "macos/gdkmacosdisplay-private.h"
#endif
#ifdef GDK_WINDOWING_WIN32
#include "win32/gdkwin32.h"
#include "win32/gdkprivate-win32.h"
@ -262,6 +266,9 @@ static GdkBackend gdk_backends[] = {
#ifdef GDK_WINDOWING_QUARTZ
{ "quartz", _gdk_quartz_display_open },
#endif
#ifdef GDK_WINDOWING_MACOS
{ "macos", _gdk_macos_display_open },
#endif
#ifdef GDK_WINDOWING_WIN32
{ "win32", _gdk_win32_display_open },
#endif

View File

@ -0,0 +1,718 @@
/* GdkMacosBaseView.c
*
* Copyright 2005-2007 Imendio AB
* Copyright 2011 Hiroyuki Yamamoto
* Copyright 2020 Red Hat, Inc.
*
* 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#import "GdkMacosBaseView.h"
#import "GdkMacosWindow.h"
#include "gdkinternals.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacossurface-private.h"
/* Text Input Client */
#define TIC_MARKED_TEXT "tic-marked-text"
#define TIC_SELECTED_POS "tic-selected-pos"
#define TIC_SELECTED_LEN "tic-selected-len"
#define TIC_INSERT_TEXT "tic-insert-text"
#define TIC_IN_KEY_DOWN "tic-in-key-down"
/* GtkIMContext */
#define GIC_CURSOR_RECT "gic-cursor-rect"
#define GIC_FILTER_KEY "gic-filter-key"
#define GIC_FILTER_PASSTHRU 0
#define GIC_FILTER_FILTERED 1
@implementation GdkMacosBaseView
-(id)initWithFrame:(NSRect)frameRect
{
if ((self = [super initWithFrame: frameRect]))
{
NSRect rect = NSMakeRect (0, 0, 0, 0);
NSTrackingAreaOptions options;
markedRange = NSMakeRange (NSNotFound, 0);
selectedRange = NSMakeRange (0, 0);
[self setValue: @(YES) forKey: @"postsFrameChangedNotifications"];
options = (NSTrackingMouseEnteredAndExited |
NSTrackingMouseMoved |
NSTrackingInVisibleRect |
NSTrackingActiveAlways);
trackingArea = [[NSTrackingArea alloc] initWithRect:rect
options:options
owner:(id)self
userInfo:nil];
[self addTrackingArea:trackingArea];
}
return self;
}
-(void)setNeedsDisplay:(BOOL)needsDisplay
{
for (id child in [self subviews])
[child setNeedsDisplay:needsDisplay];
}
-(void)setOpaqueRegion:(cairo_region_t *)region
{
/* Do nothing */
}
-(BOOL)acceptsFirstMouse
{
return YES;
}
-(BOOL)mouseDownCanMoveWindow
{
return NO;
}
-(BOOL)acceptsFirstResponder
{
GDK_NOTE (EVENTS, g_message ("acceptsFirstResponder"));
return YES;
}
-(BOOL)becomeFirstResponder
{
GDK_NOTE (EVENTS, g_message ("becomeFirstResponder"));
return YES;
}
-(BOOL)resignFirstResponder
{
GDK_NOTE (EVENTS, g_message ("resignFirstResponder"));
return YES;
}
-(void)setNeedsInvalidateShadow: (BOOL)invalidate
{
needsInvalidateShadow = invalidate;
}
-(NSTrackingArea *)trackingArea
{
return trackingArea;
}
-(GdkMacosSurface *)gdkSurface
{
return [(GdkMacosWindow *)[self window] gdkSurface];
}
-(GdkMacosDisplay *)gdkDisplay
{
GdkMacosSurface *surface = [self gdkSurface];
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (surface));
return GDK_MACOS_DISPLAY (display);
}
-(void)keyDown:(NSEvent *)theEvent
{
/* NOTE: When user press Cmd+A, interpretKeyEvents: will call noop:
* method. When user press and hold A to show the accented char window,
* it consumed repeating key down events for key 'A' do NOT call
* any other method. We use this behavior to determine if this key
* down event is filtered by interpretKeyEvents.
*/
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_FILTERED));
GDK_NOTE (EVENTS, g_message ("keyDown"));
[self interpretKeyEvents: [NSArray arrayWithObject: theEvent]];
}
-(void)flagsChanged: (NSEvent *)theEvent
{
}
-(NSUInteger)characterIndexForPoint:(NSPoint)aPoint
{
GDK_NOTE (EVENTS, g_message ("characterIndexForPoint"));
return 0;
}
-(NSRect)firstRectForCharacterRange:(NSRange)aRange actualRange: (NSRangePointer)actualRange
{
GdkRectangle *rect;
GDK_NOTE (EVENTS, g_message ("firstRectForCharacterRange"));
if ((rect = g_object_get_data (G_OBJECT ([self gdkSurface]), GIC_CURSOR_RECT)))
{
GdkMacosDisplay *display = [self gdkDisplay];
int ns_x, ns_y;
_gdk_macos_display_to_display_coords (display,
rect->x, rect->y + rect->height,
&ns_x, &ns_y);
return NSMakeRect (ns_x, ns_y, rect->width, rect->height);
}
return NSMakeRect (0, 0, 0, 0);
}
-(NSArray *)validAttributesForMarkedText
{
GDK_NOTE (EVENTS, g_message ("validAttributesForMarkedText"));
return [NSArray arrayWithObjects: NSUnderlineStyleAttributeName, nil];
}
-(NSAttributedString *)attributedSubstringForProposedRange: (NSRange)aRange actualRange: (NSRangePointer)actualRange
{
GDK_NOTE (EVENTS, g_message ("attributedSubstringForProposedRange"));
return nil;
}
-(BOOL)hasMarkedText
{
GDK_NOTE (EVENTS, g_message ("hasMarkedText"));
return markedRange.location != NSNotFound && markedRange.length != 0;
}
-(NSRange)markedRange
{
GDK_NOTE (EVENTS, g_message ("markedRange"));
return markedRange;
}
-(NSRange)selectedRange
{
GDK_NOTE (EVENTS, g_message ("selectedRange"));
return selectedRange;
}
-(void)unmarkText
{
GDK_NOTE (EVENTS, g_message ("unmarkText"));
selectedRange = NSMakeRange (0, 0);
markedRange = NSMakeRange (NSNotFound, 0);
g_object_set_data_full (G_OBJECT ([self gdkSurface]), TIC_MARKED_TEXT, NULL, g_free);
}
-(void)setMarkedText:(id)aString selectedRange: (NSRange)newSelection replacementRange: (NSRange)replacementRange
{
const char *str;
GDK_NOTE (EVENTS, g_message ("setMarkedText"));
if (replacementRange.location == NSNotFound)
{
markedRange = NSMakeRange (newSelection.location, [aString length]);
selectedRange = NSMakeRange (newSelection.location, newSelection.length);
}
else
{
markedRange = NSMakeRange (replacementRange.location, [aString length]);
selectedRange = NSMakeRange (replacementRange.location + newSelection.location, newSelection.length);
}
if ([aString isKindOfClass: [NSAttributedString class]])
str = [[aString string] UTF8String];
else
str = [aString UTF8String];
g_object_set_data_full (G_OBJECT ([self gdkSurface]), TIC_MARKED_TEXT, g_strdup (str), g_free);
g_object_set_data (G_OBJECT ([self gdkSurface]),
TIC_SELECTED_POS,
GUINT_TO_POINTER (selectedRange.location));
g_object_set_data (G_OBJECT ([self gdkSurface]),
TIC_SELECTED_LEN,
GUINT_TO_POINTER (selectedRange.length));
GDK_NOTE (EVENTS, g_message ("setMarkedText: set %s (%p, nsview %p): %s",
TIC_MARKED_TEXT, [self gdkSurface], self,
str ? str : "(empty)"));
/* handle text input changes by mouse events */
if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT ([self gdkSurface]), TIC_IN_KEY_DOWN)))
_gdk_macos_surface_synthesize_null_key ([self gdkSurface]);
}
-(void)doCommandBySelector:(SEL)aSelector
{
GDK_NOTE (EVENTS, g_message ("doCommandBySelector"));
if ([self respondsToSelector: aSelector])
[self performSelector: aSelector];
}
-(void)insertText:(id)aString replacementRange: (NSRange)replacementRange
{
const char *str;
NSString *string;
GDK_NOTE (EVENTS, g_message ("insertText"));
if ([self hasMarkedText])
[self unmarkText];
if ([aString isKindOfClass: [NSAttributedString class]])
string = [aString string];
else
string = aString;
NSCharacterSet *ctrlChars = [NSCharacterSet controlCharacterSet];
NSCharacterSet *wsnlChars = [NSCharacterSet whitespaceAndNewlineCharacterSet];
if ([string rangeOfCharacterFromSet:ctrlChars].length &&
[string rangeOfCharacterFromSet:wsnlChars].length == 0)
{
/* discard invalid text input with Chinese input methods */
str = "";
[self unmarkText];
[[NSTextInputContext currentInputContext] discardMarkedText];
}
else
{
str = [string UTF8String];
}
g_object_set_data_full (G_OBJECT ([self gdkSurface]), TIC_INSERT_TEXT, g_strdup (str), g_free);
GDK_NOTE (EVENTS, g_message ("insertText: set %s (%p, nsview %p): %s",
TIC_INSERT_TEXT, [self gdkSurface], self,
str ? str : "(empty)"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_FILTERED));
/* handle text input changes by mouse events */
if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT ([self gdkSurface]), TIC_IN_KEY_DOWN)))
_gdk_macos_surface_synthesize_null_key ([self gdkSurface]);
}
-(void)deleteBackward:(id)sender
{
GDK_NOTE (EVENTS, g_message ("deleteBackward"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)deleteForward:(id)sender
{
GDK_NOTE (EVENTS, g_message ("deleteForward"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)deleteToBeginningOfLine:(id)sender
{
GDK_NOTE (EVENTS, g_message ("deleteToBeginningOfLine"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)deleteToEndOfLine:(id)sender
{
GDK_NOTE (EVENTS, g_message ("deleteToEndOfLine"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)deleteWordBackward:(id)sender
{
GDK_NOTE (EVENTS, g_message ("deleteWordBackward"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)deleteWordForward:(id)sender
{
GDK_NOTE (EVENTS, g_message ("deleteWordForward"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)insertBacktab:(id)sender
{
GDK_NOTE (EVENTS, g_message ("insertBacktab"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)insertNewline:(id)sender
{
GDK_NOTE (EVENTS, g_message ("insertNewline"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)insertTab:(id)sender
{
GDK_NOTE (EVENTS, g_message ("insertTab"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveBackward:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveBackward"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveBackwardAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveBackwardAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveDown:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveDown"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveDownAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveDownAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveForward:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveForward"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveForwardAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveForwardAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveLeft:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveLeft"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveLeftAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveLeftAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveRight:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveRight"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveRightAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveRightAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToBeginningOfDocument:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToBeginningOfDocument"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToBeginningOfDocumentAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToBeginningOfDocumentAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToBeginningOfLine:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToBeginningOfLine"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToBeginningOfLineAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToBeginningOfLineAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToEndOfDocument:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToEndOfDocument"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToEndOfDocumentAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToEndOfDocumentAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToEndOfLine:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToEndOfLine"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToEndOfLineAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToEndOfLineAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveUp:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveUp"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveUpAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveUpAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordBackward:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordBackward"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordBackwardAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordBackwardAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordForward:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordForward"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordForwardAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordForwardAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordLeft:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordLeft"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordLeftAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordLeftAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordRight:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordRight"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordRightAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordRightAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)pageDown:(id)sender
{
GDK_NOTE (EVENTS, g_message ("pageDown"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)pageDownAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("pageDownAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)pageUp:(id)sender
{
GDK_NOTE (EVENTS, g_message ("pageUp"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)pageUpAndModifySelection:(id)sender
{
GDK_NOTE (EVENTS, g_message ("pageUpAndModifySelection"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)selectAll:(id)sender
{
GDK_NOTE (EVENTS, g_message ("selectAll"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)selectLine:(id)sender
{
GDK_NOTE (EVENTS, g_message ("selectLine"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)selectWord:(id)sender
{
GDK_NOTE (EVENTS, g_message ("selectWord"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)noop: (id)sender
{
GDK_NOTE (EVENTS, g_message ("noop"));
g_object_set_data (G_OBJECT ([self gdkSurface]),
GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
@end

View File

@ -1,6 +1,7 @@
/* GdkQuartzView.h
/* GdkMacosBaseView.h
*
* Copyright (C) 2005 Imendio AB
* Copyright © 2020 Red Hat, Inc.
* Copyright © 2005-2007 Imendio AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -14,36 +15,32 @@
*
* 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#import <AppKit/AppKit.h>
#include "gdk/gdk.h"
#import <Foundation/Foundation.h>
/* Text Input Client */
#define TIC_MARKED_TEXT "tic-marked-text"
#define TIC_SELECTED_POS "tic-selected-pos"
#define TIC_SELECTED_LEN "tic-selected-len"
#define TIC_INSERT_TEXT "tic-insert-text"
#define TIC_IN_KEY_DOWN "tic-in-key-down"
#include <gdk/gdk.h>
/* GtkIMContext */
#define GIC_CURSOR_RECT "gic-cursor-rect"
#define GIC_FILTER_KEY "gic-filter-key"
#define GIC_FILTER_PASSTHRU 0
#define GIC_FILTER_FILTERED 1
#include "gdkmacosdisplay.h"
#include "gdkmacossurface.h"
@interface GdkQuartzView : NSView <NSTextInputClient>
#define GDK_IS_MACOS_BASE_VIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosBaseView class]])
@interface GdkMacosBaseView : NSView <NSTextInputClient>
{
GdkSurface *gdk_surface;
NSTrackingRectTag trackingRect;
NSTrackingArea *trackingArea;
BOOL needsInvalidateShadow;
NSRange markedRange;
NSRange selectedRange;
}
- (void)setGdkSurface: (GdkSurface *)window;
- (GdkSurface *)gdkSurface;
- (NSTrackingRectTag)trackingRect;
- (void)setNeedsInvalidateShadow: (BOOL)invalidate;
-(GdkMacosSurface *)gdkSurface;
-(GdkMacosDisplay *)gdkDisplay;
-(void)setNeedsInvalidateShadow: (BOOL)invalidate;
-(NSTrackingArea *)trackingArea;
-(void)setOpaqueRegion:(cairo_region_t *)region;
@end

View File

@ -0,0 +1,171 @@
/* GdkMacosCairoSubview.c
*
* Copyright © 2020 Red Hat, Inc.
*
* 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include <CoreGraphics/CoreGraphics.h>
#include <cairo-quartz.h>
#include "gdkinternals.h"
#import "GdkMacosCairoSubview.h"
#import "GdkMacosCairoView.h"
#include "gdkmacossurface-private.h"
@implementation GdkMacosCairoSubview
-(BOOL)isOpaque
{
return _isOpaque;
}
-(BOOL)isFlipped
{
return YES;
}
-(GdkSurface *)gdkSurface
{
return GDK_SURFACE ([(GdkMacosBaseView *)[self superview] gdkSurface]);
}
-(void)drawRect:(NSRect)rect
{
CGContextRef cgContext;
GdkSurface *gdk_surface;
cairo_surface_t *dest;
const NSRect *rects = NULL;
NSView *root_view;
NSInteger n_rects = 0;
NSRect abs_bounds;
cairo_t *cr;
CGSize scale;
int scale_factor;
if (self->cairoSurface == NULL)
return;
/* Acquire everything we need to do translations, drawing, etc */
gdk_surface = [self gdkSurface];
scale_factor = gdk_surface_get_scale_factor (gdk_surface);
root_view = [[self window] contentView];
cgContext = [[NSGraphicsContext currentContext] CGContext];
abs_bounds = [self convertRect:[self bounds] toView:root_view];
CGContextSaveGState (cgContext);
/* Translate scaling to remove HiDPI scaling from CGContext as
* cairo will be doing that for us already.
*/
scale = CGSizeMake (1.0, 1.0);
scale = CGContextConvertSizeToDeviceSpace (cgContext, scale);
CGContextScaleCTM (cgContext, 1.0 / scale.width, 1.0 / scale.height);
/* Create the cairo surface to draw to the CGContext and translate
* coordinates so we can pretend we are in the same coordinate system
* as the GDK surface.
*/
dest = cairo_quartz_surface_create_for_cg_context (cgContext,
gdk_surface->width * scale_factor,
gdk_surface->height * scale_factor);
cairo_surface_set_device_scale (dest, scale_factor, scale_factor);
/* Create cairo context and translate things into the origin of
* the topmost contentView so that we just draw at 0,0 with a
* clip region to paint the surface.
*/
cr = cairo_create (dest);
cairo_translate (cr, -abs_bounds.origin.x, -abs_bounds.origin.y);
/* Clip the cairo context based on the rectangles to be drawn
* within the bounding box :rect.
*/
[self getRectsBeingDrawn:&rects count:&n_rects];
for (NSInteger i = 0; i < n_rects; i++)
{
NSRect area = [self convertRect:rects[i] toView:root_view];
cairo_rectangle (cr,
area.origin.x, area.origin.y,
area.size.width, area.size.height);
}
cairo_clip (cr);
/* Now paint the surface (without blending) as we do not need
* any compositing here. The transparent regions (like shadows)
* are already on non-opaque layers.
*/
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_set_source_surface (cr, self->cairoSurface, 0, 0);
cairo_paint (cr);
/* Cleanup state, flush the surface to the backing layer, and
* restore GState for future use.
*/
cairo_destroy (cr);
cairo_surface_flush (dest);
cairo_surface_destroy (dest);
CGContextRestoreGState (cgContext);
}
-(void)setCairoSurface:(cairo_surface_t *)surface
withDamage:(cairo_region_t *)region
{
if (surface != self->cairoSurface)
{
g_clear_pointer (&self->cairoSurface, cairo_surface_destroy);
if (surface != NULL)
self->cairoSurface = cairo_surface_reference (surface);
}
if (region != NULL)
{
NSView *root_view = [[self window] contentView];
NSRect abs_bounds = [self convertRect:[self bounds] toView:root_view];
guint n_rects = cairo_region_num_rectangles (region);
for (guint i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
NSRect nsrect;
cairo_region_get_rectangle (region, i, &rect);
nsrect = NSMakeRect (rect.x, rect.y, rect.width, rect.height);
if (NSIntersectsRect (abs_bounds, nsrect))
{
nsrect.origin.x -= abs_bounds.origin.x;
nsrect.origin.y -= abs_bounds.origin.y;
[self setNeedsDisplayInRect:nsrect];
}
}
}
for (id view in [self subviews])
[(GdkMacosCairoSubview *)view setCairoSurface:surface
withDamage:region];
}
-(void)setOpaque:(BOOL)opaque
{
self->_isOpaque = opaque;
}
@end

View File

@ -0,0 +1,35 @@
/* GdkMacosCairoSubview.h
*
* Copyright © 2020 Red Hat, Inc.
*
* 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include <AppKit/AppKit.h>
#define GDK_IS_MACOS_CAIRO_SUBVIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosCairoSubview class]])
@interface GdkMacosCairoSubview : NSView
{
BOOL _isOpaque;
cairo_surface_t *cairoSurface;
}
-(void)setOpaque:(BOOL)opaque;
-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
withDamage:(cairo_region_t *)region;
@end

View File

@ -0,0 +1,170 @@
/* GdkMacosCairoView.c
*
* Copyright © 2020 Red Hat, Inc.
* Copyright © 2005-2007 Imendio AB
*
* 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include <CoreGraphics/CoreGraphics.h>
#include <cairo-quartz.h>
#include "gdkinternals.h"
#import "GdkMacosCairoView.h"
#import "GdkMacosCairoSubview.h"
#include "gdkmacossurface-private.h"
@implementation GdkMacosCairoView
-(void)dealloc
{
g_clear_pointer (&self->opaque, g_ptr_array_unref);
self->transparent = NULL;
[super dealloc];
}
-(BOOL)isOpaque
{
if ([self window])
return [[self window] isOpaque];
return YES;
}
-(BOOL)isFlipped
{
return YES;
}
-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
withDamage:(cairo_region_t *)cairoRegion
{
for (id view in [self subviews])
[(GdkMacosCairoSubview *)view setCairoSurface:cairoSurface
withDamage:cairoRegion];
}
-(void)removeOpaqueChildren
{
[[self->transparent subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
if (self->opaque->len)
g_ptr_array_remove_range (self->opaque, 0, self->opaque->len);
}
-(void)setOpaqueRegion:(cairo_region_t *)region
{
NSRect abs_bounds;
guint n_rects;
if (region == NULL)
return;
abs_bounds = [self convertRect:[self bounds] toView:nil];
n_rects = cairo_region_num_rectangles (region);
/* The common case (at least for opaque windows and CSD) is that we will
* have either one or two opaque rectangles. If we detect that the same
* number of them are available as the previous, we can just resize the
* previous ones to avoid adding/removing views at a fast rate while
* resizing.
*/
if (n_rects == self->opaque->len)
{
for (guint i = 0; i < n_rects; i++)
{
GdkMacosCairoSubview *child;
cairo_rectangle_int_t rect;
child = g_ptr_array_index (self->opaque, i);
cairo_region_get_rectangle (region, i, &rect);
[child setFrame:NSMakeRect (rect.x - abs_bounds.origin.x,
rect.y - abs_bounds.origin.y,
rect.width,
rect.height)];
}
return;
}
[self removeOpaqueChildren];
for (guint i = 0; i < n_rects; i++)
{
GdkMacosCairoSubview *child;
cairo_rectangle_int_t rect;
NSRect nsrect;
cairo_region_get_rectangle (region, i, &rect);
nsrect = NSMakeRect (rect.x - abs_bounds.origin.x,
rect.y - abs_bounds.origin.y,
rect.width,
rect.height);
child = [[GdkMacosCairoSubview alloc] initWithFrame:nsrect];
[child setOpaque:YES];
[child setWantsLayer:YES];
[self->transparent addSubview:child];
g_ptr_array_add (self->opaque, child);
}
}
-(NSView *)initWithFrame:(NSRect)frame
{
if ((self = [super initWithFrame:frame]))
{
/* An array to track all the opaque children placed into
* the child self->transparent. This allows us to reuse them
* when we receive a new opaque area instead of discarding
* them on each draw.
*/
self->opaque = g_ptr_array_new ();
/* Setup our primary subview which will render all content that is not
* within an opaque region (such as shadows for CSD windows). For opaque
* windows, this will all be obscurred by other views, so it doesn't
* matter much to have it here.
*/
self->transparent = [[GdkMacosCairoSubview alloc] initWithFrame:frame];
[self addSubview:self->transparent];
}
return self;
}
-(void)setFrame:(NSRect)rect
{
[super setFrame:rect];
[self->transparent setFrame:NSMakeRect (0, 0, rect.size.width, rect.size.height)];
}
-(BOOL)acceptsFirstMouse
{
return YES;
}
-(BOOL)mouseDownCanMoveWindow
{
return NO;
}
@end

View File

@ -1,7 +1,7 @@
/* gdkdevicemanager-quartz.h
/* GdkMacosCairoView.h
*
* Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
* Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
* Copyright © 2020 Red Hat, Inc.
* Copyright © 2005-2007 Imendio AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -15,28 +15,23 @@
*
* 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_QUARTZ_DEVICE_MANAGER_CORE__
#define __GDK_QUARTZ_DEVICE_MANAGER_CORE__
#include <cairo.h>
#include <gdkdevicemanagerprivate.h>
#include "gdkquartzdevicemanager-core.h"
#import "GdkMacosBaseView.h"
G_BEGIN_DECLS
#define GDK_IS_MACOS_CAIRO_VIEW(obj) ((obj) && [obj isKindOfClass:[GdkMacosCairoView class]])
struct _GdkQuartzDeviceManagerCore
@interface GdkMacosCairoView : GdkMacosBaseView
{
GObject parent_object;
GdkDevice *core_pointer;
GdkDevice *core_keyboard;
};
NSView *transparent;
GPtrArray *opaque;
}
struct _GdkQuartzDeviceManagerCoreClass
{
GObjectClass parent_class;
};
-(void)setCairoSurface:(cairo_surface_t *)cairoSurface
withDamage:(cairo_region_t *)region;
G_END_DECLS
#endif /* __GDK_QUARTZ_DEVICE_MANAGER__ */
@end

157
gdk/macos/GdkMacosGLLayer.c Normal file
View File

@ -0,0 +1,157 @@
/* GdkMacosGLLayer.c
*
* Copyright © 2020 Red Hat, Inc.
*
* 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/* Based on Chromium image_transport_surface_calayer_mac.mm
* See the BSD-style license above.
*/
#include "config.h"
#include <OpenGL/gl.h>
#import "GdkMacosGLLayer.h"
@implementation GdkMacosGLLayer
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-(id)initWithContext:(NSOpenGLContext *)shared
{
[super init];
_shared = [shared retain];
return self;
}
-(void)dealloc
{
[_shared release];
_shared = nil;
[super dealloc];
}
-(void)setContentsRect:(NSRect)bounds
{
_pixelSize = bounds.size;
[super setContentsRect:bounds];
}
-(CGLPixelFormatObj)copyCGLPixelFormatForDisplayMask:(uint32_t)mask
{
return CGLRetainPixelFormat ([[_shared pixelFormat] CGLPixelFormatObj]);
}
-(CGLContextObj)copyCGLContextForPixelFormat:(CGLPixelFormatObj)pixelFormat
{
CGLContextObj context = NULL;
CGLCreateContext (pixelFormat, [_shared CGLContextObj], &context);
return context;
}
-(BOOL)canDrawInCGLContext:(CGLContextObj)glContext
pixelFormat:(CGLPixelFormatObj)pixelFormat
forLayerTime:(CFTimeInterval)timeInterval
displayTime:(const CVTimeStamp*)timeStamp
{
return YES;
}
-(void)drawInCGLContext:(CGLContextObj)glContext
pixelFormat:(CGLPixelFormatObj)pixelFormat
forLayerTime:(CFTimeInterval)timeInterval
displayTime:(const CVTimeStamp*)timeStamp
{
if (_texture == 0)
return;
glClearColor (1, 0, 1, 1);
glClear (GL_COLOR_BUFFER_BIT);
GLint viewport[4] = {0, 0, 0, 0};
glGetIntegerv (GL_VIEWPORT, viewport);
NSSize viewportSize = NSMakeSize (viewport[2], viewport[3]);
/* Set the coordinate system to be one-to-one with pixels. */
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0, viewportSize.width, 0, viewportSize.height, -1, 1);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
/* Draw a fullscreen quad. */
glColor4f (1, 1, 1, 1);
glEnable (GL_TEXTURE_RECTANGLE_ARB);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, _texture);
glBegin (GL_QUADS);
{
glTexCoord2f (0, 0);
glVertex2f (0, 0);
glTexCoord2f (0, _pixelSize.height);
glVertex2f (0, _pixelSize.height);
glTexCoord2f (_pixelSize.width, _pixelSize.height);
glVertex2f (_pixelSize.width, _pixelSize.height);
glTexCoord2f (_pixelSize.width, 0);
glVertex2f (_pixelSize.width, 0);
}
glEnd ();
glBindTexture (0, _texture);
glDisable (GL_TEXTURE_RECTANGLE_ARB);
[super drawInCGLContext:glContext
pixelFormat:pixelFormat
forLayerTime:timeInterval
displayTime:timeStamp];
}
-(void)setTexture:(GLuint)texture
{
_texture = texture;
[self setNeedsDisplay];
}
G_GNUC_END_IGNORE_DEPRECATIONS
@end

View File

@ -1,6 +1,6 @@
/* gdkscreen-quartz.h
/* GdkMacosGLLayer.h
*
* Copyright (C) 2009,2010 Kristian Rietveld <kris@gtk.org>
* Copyright © 2020 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -14,36 +14,27 @@
*
* 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_QUARTZ_SCREEN__
#define __GDK_QUARTZ_SCREEN__
#include <AppKit/AppKit.h>
#include <glib.h>
G_BEGIN_DECLS
#define GDK_IS_MACOS_GL_LAYER(obj) ((obj) && [obj isKindOfClass:[GdkMacosGLLayer class]])
struct _GdkQuartzScreen
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
@interface GdkMacosGLLayer : CAOpenGLLayer
{
GObject parent_instance;
NSOpenGLContext *_shared;
GLuint _texture;
NSSize _pixelSize;
}
GdkDisplay *display;
-(id)initWithContext:(NSOpenGLContext *)shared;
-(void)setTexture:(GLuint)texture;
/* Origin of "root window" in Cocoa coordinates */
gint min_x;
gint min_y;
@end
gint width;
gint height;
guint screen_changed_id;
guint emit_monitors_changed : 1;
};
struct _GdkQuartzScreenClass
{
GObjectClass parent_class;
};
G_END_DECLS
#endif /* __GDK_QUARTZ_SCREEN__ */
G_GNUC_END_IGNORE_DEPRECATIONS

732
gdk/macos/GdkMacosWindow.c Normal file
View File

@ -0,0 +1,732 @@
/* GdkMacosWindow.m
*
* Copyright © 2020 Red Hat, Inc.
* Copyright © 2005-2007 Imendio AB
*
* 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include <gdk/gdk.h>
#import "GdkMacosBaseView.h"
#import "GdkMacosCairoView.h"
#import "GdkMacosWindow.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacossurface-private.h"
#include "gdkmacospopupsurface-private.h"
#include "gdkmacostoplevelsurface-private.h"
#include "gdkmonitorprivate.h"
#include "gdksurfaceprivate.h"
@implementation GdkMacosWindow
-(BOOL)windowShouldClose:(id)sender
{
GdkDisplay *display;
GdkEvent *event;
GList *node;
display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
event = gdk_delete_event_new (GDK_SURFACE (gdk_surface));
node = _gdk_event_queue_append (display, event);
_gdk_windowing_got_event (display, node, event,
_gdk_display_get_next_serial (display));
return NO;
}
-(void)windowWillMiniaturize:(NSNotification *)aNotification
{
if (GDK_IS_MACOS_TOPLEVEL_SURFACE (gdk_surface))
_gdk_macos_toplevel_surface_detach_from_parent (GDK_MACOS_TOPLEVEL_SURFACE (gdk_surface));
else if (GDK_IS_MACOS_POPUP_SURFACE (gdk_surface))
_gdk_macos_popup_surface_detach_from_parent (GDK_MACOS_POPUP_SURFACE (gdk_surface));
}
-(void)windowDidMiniaturize:(NSNotification *)aNotification
{
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_SURFACE_STATE_MINIMIZED);
}
-(void)windowDidDeminiaturize:(NSNotification *)aNotification
{
if (GDK_IS_MACOS_TOPLEVEL_SURFACE (gdk_surface))
_gdk_macos_toplevel_surface_attach_to_parent (GDK_MACOS_TOPLEVEL_SURFACE (gdk_surface));
else if (GDK_IS_MACOS_POPUP_SURFACE (gdk_surface))
_gdk_macos_popup_surface_attach_to_parent (GDK_MACOS_POPUP_SURFACE (gdk_surface));
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), GDK_SURFACE_STATE_MINIMIZED, 0);
}
-(void)windowDidBecomeKey:(NSNotification *)aNotification
{
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_SURFACE_STATE_FOCUSED);
_gdk_macos_display_surface_became_key ([self gdkDisplay], gdk_surface);
}
-(void)windowDidResignKey:(NSNotification *)aNotification
{
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), GDK_SURFACE_STATE_FOCUSED, 0);
_gdk_macos_display_surface_resigned_key ([self gdkDisplay], gdk_surface);
}
-(void)windowDidBecomeMain:(NSNotification *)aNotification
{
if (![self isVisible])
{
/* Note: This is a hack needed because for unknown reasons, hidden
* windows get shown when clicking the dock icon when the application
* is not already active.
*/
[self orderOut:nil];
return;
}
_gdk_macos_display_surface_became_main ([self gdkDisplay], gdk_surface);
}
-(void)windowDidResignMain:(NSNotification *)aNotification
{
_gdk_macos_display_surface_resigned_main ([self gdkDisplay], gdk_surface);
}
/* Used in combination with NSLeftMouseUp in sendEvent to keep track
* of when the window is being moved with the mouse.
*/
-(void)windowWillMove:(NSNotification *)aNotification
{
inMove = YES;
}
-(void)sendEvent:(NSEvent *)event
{
NSEventType event_type = [event type];
switch ((int)event_type)
{
case NSEventTypeLeftMouseUp: {
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
double time = ((double)[event timestamp]) * 1000.0;
_gdk_macos_display_break_all_grabs (GDK_MACOS_DISPLAY (display), time);
inManualMove = NO;
inManualResize = NO;
inMove = NO;
/* We need to deliver the event to the proper drag gestures or we
* will leave the window in inconsistent state that requires clicking
* in the window to cancel the gesture.
*
* TODO: Can we improve grab breaking to fix this?
*/
_gdk_macos_display_send_button_event ([self gdkDisplay], event);
break;
}
case NSEventTypeLeftMouseDragged:
if ([self trackManualMove] || [self trackManualResize])
return;
break;
default:
break;
}
[super sendEvent:event];
}
-(BOOL)isInMove
{
return inMove;
}
-(void)checkSendEnterNotify
{
/* When a new window has been created, and the mouse is in the window
* area, we will not receive an NSEventTypeMouseEntered event.
* Therefore, we synthesize an enter notify event manually.
*/
if (!initialPositionKnown)
{
initialPositionKnown = YES;
if (NSPointInRect ([NSEvent mouseLocation], [self frame]))
{
GdkMacosBaseView *view = (GdkMacosBaseView *)[self contentView];
NSEvent *event;
event = [NSEvent enterExitEventWithType: NSEventTypeMouseEntered
location: [self mouseLocationOutsideOfEventStream]
modifierFlags: 0
timestamp: [[NSApp currentEvent] timestamp]
windowNumber: [self windowNumber]
context: NULL
eventNumber: 0
trackingNumber: (NSInteger)[view trackingArea]
userData: nil];
[NSApp postEvent:event atStart:NO];
}
}
}
-(void)windowDidUnmaximize
{
NSWindowStyleMask style_mask = [self styleMask];
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), GDK_SURFACE_STATE_MAXIMIZED, 0);
/* If we are using CSD, then we transitioned to an opaque
* window while we were maximized. Now we need to drop that
* as we are leaving maximized state.
*/
if ((style_mask & NSWindowStyleMaskTitled) == 0 && [self isOpaque])
[self setOpaque:NO];
}
-(void)windowDidMove:(NSNotification *)aNotification
{
GdkSurface *surface = GDK_SURFACE (gdk_surface);
gboolean maximized = (surface->state & GDK_SURFACE_STATE_MAXIMIZED) != 0;
/* In case the window is changed when maximized remove the maximized state */
if (maximized && !inMaximizeTransition && !NSEqualRects (lastMaximizedFrame, [self frame]))
[self windowDidUnmaximize];
_gdk_macos_surface_update_position (gdk_surface);
_gdk_macos_surface_reposition_children (gdk_surface);
[self checkSendEnterNotify];
}
-(void)windowDidResize:(NSNotification *)aNotification
{
NSRect content_rect;
GdkSurface *surface;
GdkDisplay *display;
GdkEvent *event;
gboolean maximized;
GList *node;
surface = GDK_SURFACE (gdk_surface);
display = gdk_surface_get_display (surface);
content_rect = [self contentRectForFrameRect:[self frame]];
maximized = (surface->state & GDK_SURFACE_STATE_MAXIMIZED) != 0;
/* see same in windowDidMove */
if (maximized && !inMaximizeTransition && !NSEqualRects (lastMaximizedFrame, [self frame]))
[self windowDidUnmaximize];
surface->width = content_rect.size.width;
surface->height = content_rect.size.height;
/* Certain resize operations (e.g. going fullscreen), also move the
* origin of the window.
*/
_gdk_macos_surface_update_position (GDK_MACOS_SURFACE (surface));
[[self contentView] setFrame:NSMakeRect (0, 0, surface->width, surface->height)];
_gdk_surface_update_size (surface);
/* Synthesize a configure event */
event = gdk_configure_event_new (surface,
content_rect.size.width,
content_rect.size.height);
node = _gdk_event_queue_append (display, event);
_gdk_windowing_got_event (display, node, event,
_gdk_display_get_next_serial (display));
_gdk_macos_surface_reposition_children (gdk_surface);
[self checkSendEnterNotify];
}
-(id)initWithContentRect:(NSRect)contentRect
styleMask:(NSWindowStyleMask)styleMask
backing:(NSBackingStoreType)backingType
defer:(BOOL)flag
screen:(NSScreen *)screen
{
GdkMacosCairoView *view;
self = [super initWithContentRect:contentRect
styleMask:styleMask
backing:backingType
defer:flag
screen:screen];
[self setAcceptsMouseMovedEvents:YES];
[self setDelegate:(id<NSWindowDelegate>)self];
[self setReleasedWhenClosed:YES];
view = [[GdkMacosCairoView alloc] initWithFrame:contentRect];
[self setContentView:view];
[view release];
return self;
}
-(BOOL)canBecomeMainWindow
{
return GDK_IS_TOPLEVEL (gdk_surface);
}
-(BOOL)canBecomeKeyWindow
{
return GDK_IS_TOPLEVEL (gdk_surface);
}
-(void)showAndMakeKey:(BOOL)makeKey
{
inShowOrHide = YES;
if (makeKey && [self canBecomeKeyWindow])
[self makeKeyAndOrderFront:nil];
else
[self orderFront:nil];
inShowOrHide = NO;
[self checkSendEnterNotify];
}
-(void)hide
{
inShowOrHide = YES;
[self orderOut:nil];
inShowOrHide = NO;
initialPositionKnown = NO;
}
-(BOOL)trackManualMove
{
NSRect windowFrame;
NSPoint currentLocation;
GdkMonitor *monitor;
GdkRectangle geometry;
GdkRectangle workarea;
int shadow_top = 0;
int shadow_left = 0;
int shadow_right = 0;
int shadow_bottom = 0;
GdkRectangle window_gdk;
GdkPoint pointer_position;
GdkPoint new_origin;
if (!inManualMove)
return NO;
/* Get our shadow so we can adjust the window position sans-shadow */
_gdk_macos_surface_get_shadow (gdk_surface,
&shadow_top,
&shadow_right,
&shadow_bottom,
&shadow_left);
windowFrame = [self frame];
currentLocation = [NSEvent mouseLocation];
/* Update the snapping geometry to match the current monitor */
monitor = _gdk_macos_display_get_monitor_at_display_coords ([self gdkDisplay],
currentLocation.x,
currentLocation.y);
gdk_monitor_get_geometry (monitor, &geometry);
gdk_monitor_get_workarea (monitor, &workarea);
_edge_snapping_set_monitor (&self->snapping, &geometry, &workarea);
/* Convert origins to GDK coordinates */
_gdk_macos_display_from_display_coords ([self gdkDisplay],
currentLocation.x,
currentLocation.y,
&pointer_position.x,
&pointer_position.y);
_gdk_macos_display_from_display_coords ([self gdkDisplay],
windowFrame.origin.x,
windowFrame.origin.y + windowFrame.size.height,
&window_gdk.x,
&window_gdk.y);
window_gdk.width = windowFrame.size.width;
window_gdk.height = windowFrame.size.height;
/* Subtract our shadowin from the window */
window_gdk.x += shadow_left;
window_gdk.y += shadow_top;
window_gdk.width = window_gdk.width - shadow_left - shadow_right;
window_gdk.height = window_gdk.height - shadow_top - shadow_bottom;
/* Now place things on the monitor */
_edge_snapping_motion (&self->snapping, &pointer_position, &window_gdk);
/* And add our shadow back to the frame */
window_gdk.x -= shadow_left;
window_gdk.y -= shadow_top;
window_gdk.width += shadow_left + shadow_right;
window_gdk.height += shadow_top + shadow_bottom;
/* Convert to quartz coordiantes */
_gdk_macos_display_to_display_coords ([self gdkDisplay],
window_gdk.x,
window_gdk.y + window_gdk.height,
&new_origin.x, &new_origin.y);
windowFrame.origin.x = new_origin.x;
windowFrame.origin.y = new_origin.y;
/* And now apply the frame to the window */
[self setFrameOrigin:NSMakePoint(new_origin.x, new_origin.y)];
return YES;
}
/* Used by gdkmacosdisplay-translate.c to decide if our sendEvent() handler
* above will see the event or if it will be subjected to standard processing
* by GDK.
*/
-(BOOL)isInManualResizeOrMove
{
return inManualResize || inManualMove;
}
-(void)beginManualMove
{
NSPoint initialMoveLocation;
GdkPoint point;
GdkMonitor *monitor;
GdkRectangle geometry;
GdkRectangle area;
GdkRectangle workarea;
if (inMove || inManualMove || inManualResize)
return;
inManualMove = YES;
monitor = _gdk_macos_surface_get_best_monitor ([self gdkSurface]);
gdk_monitor_get_geometry (monitor, &geometry);
gdk_monitor_get_workarea (monitor, &workarea);
initialMoveLocation = [NSEvent mouseLocation];
_gdk_macos_display_from_display_coords ([self gdkDisplay],
initialMoveLocation.x,
initialMoveLocation.y,
&point.x,
&point.y);
area.x = gdk_surface->root_x;
area.y = gdk_surface->root_y;
area.width = GDK_SURFACE (gdk_surface)->width;
area.height = GDK_SURFACE (gdk_surface)->height;
_edge_snapping_init (&self->snapping,
&geometry,
&workarea,
&point,
&area);
}
-(BOOL)trackManualResize
{
NSPoint mouse_location;
NSRect new_frame;
float mdx, mdy, dw, dh, dx, dy;
NSSize min_size;
if (!inManualResize || inTrackManualResize)
return NO;
inTrackManualResize = YES;
mouse_location = [self convertPointToScreen:[self mouseLocationOutsideOfEventStream]];
mdx = initialResizeLocation.x - mouse_location.x;
mdy = initialResizeLocation.y - mouse_location.y;
/* Set how a mouse location delta translates to changes in width,
* height and position.
*/
dw = dh = dx = dy = 0.0;
if (resizeEdge == GDK_SURFACE_EDGE_EAST ||
resizeEdge == GDK_SURFACE_EDGE_NORTH_EAST ||
resizeEdge == GDK_SURFACE_EDGE_SOUTH_EAST)
{
dw = -1.0;
}
if (resizeEdge == GDK_SURFACE_EDGE_NORTH ||
resizeEdge == GDK_SURFACE_EDGE_NORTH_WEST ||
resizeEdge == GDK_SURFACE_EDGE_NORTH_EAST)
{
dh = -1.0;
}
if (resizeEdge == GDK_SURFACE_EDGE_SOUTH ||
resizeEdge == GDK_SURFACE_EDGE_SOUTH_WEST ||
resizeEdge == GDK_SURFACE_EDGE_SOUTH_EAST)
{
dh = 1.0;
dy = -1.0;
}
if (resizeEdge == GDK_SURFACE_EDGE_WEST ||
resizeEdge == GDK_SURFACE_EDGE_NORTH_WEST ||
resizeEdge == GDK_SURFACE_EDGE_SOUTH_WEST)
{
dw = 1.0;
dx = -1.0;
}
/* Apply changes to the frame captured when we started resizing */
new_frame = initialResizeFrame;
new_frame.origin.x += mdx * dx;
new_frame.origin.y += mdy * dy;
new_frame.size.width += mdx * dw;
new_frame.size.height += mdy * dh;
/* In case the resulting window would be too small reduce the
* change to both size and position.
*/
min_size = [self contentMinSize];
if (new_frame.size.width < min_size.width)
{
if (dx)
new_frame.origin.x -= min_size.width - new_frame.size.width;
new_frame.size.width = min_size.width;
}
if (new_frame.size.height < min_size.height)
{
if (dy)
new_frame.origin.y -= min_size.height - new_frame.size.height;
new_frame.size.height = min_size.height;
}
/* We could also apply aspect ratio:
new_frame.size.height = new_frame.size.width / [self aspectRatio].width * [self aspectRatio].height;
*/
[self setFrame:new_frame display:YES];
/* Let the resizing be handled by GTK+. */
if (g_main_context_pending (NULL))
g_main_context_iteration (NULL, FALSE);
inTrackManualResize = NO;
return YES;
}
-(void)beginManualResize:(GdkSurfaceEdge)edge
{
if (inMove || inManualMove || inManualResize)
return;
inManualResize = YES;
resizeEdge = edge;
initialResizeFrame = [self frame];
initialResizeLocation = [self convertPointToScreen:[self mouseLocationOutsideOfEventStream]];
}
-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
return NSDragOperationNone;
}
-(void)draggingEnded:(id <NSDraggingInfo>)sender
{
}
-(void)draggingExited:(id <NSDraggingInfo>)sender
{
}
-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
{
return NSDragOperationNone;
}
-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
return YES;
}
-(BOOL)wantsPeriodicDraggingUpdates
{
return NO;
}
-(void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
{
}
-(void)setStyleMask:(NSWindowStyleMask)styleMask
{
gboolean was_fullscreen;
gboolean is_fullscreen;
gboolean was_opaque;
gboolean is_opaque;
was_fullscreen = (([self styleMask] & NSWindowStyleMaskFullScreen) != 0);
was_opaque = (([self styleMask] & NSWindowStyleMaskTitled) != 0);
[super setStyleMask:styleMask];
is_fullscreen = (([self styleMask] & NSWindowStyleMaskFullScreen) != 0);
is_opaque = (([self styleMask] & NSWindowStyleMaskTitled) != 0);
if (was_fullscreen != is_fullscreen)
_gdk_macos_surface_update_fullscreen_state (gdk_surface);
if (was_opaque != is_opaque)
{
[self setOpaque:is_opaque];
if (!is_opaque)
[self setBackgroundColor:[NSColor clearColor]];
}
}
-(NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
{
GdkMacosSurface *surface = gdk_surface;
NSRect rect;
gint shadow_top;
/* Allow the window to move up "shadow_top" more than normally allowed
* by the default impl. This makes it possible to move windows with
* client side shadow right up to the screen's menu bar. */
_gdk_macos_surface_get_shadow (surface, &shadow_top, NULL, NULL, NULL);
rect = [super constrainFrameRect:frameRect toScreen:screen];
if (frameRect.origin.y > rect.origin.y)
rect.origin.y = MIN (frameRect.origin.y, rect.origin.y + shadow_top);
return rect;
}
-(NSRect)windowWillUseStandardFrame:(NSWindow *)nsWindow
defaultFrame:(NSRect)newFrame
{
NSRect screenFrame = [[self screen] visibleFrame];
GdkMacosSurface *surface = gdk_surface;
gboolean maximized = GDK_SURFACE (surface)->state & GDK_SURFACE_STATE_MAXIMIZED;
if (!maximized)
return screenFrame;
else
return lastUnmaximizedFrame;
}
-(BOOL)windowShouldZoom:(NSWindow *)nsWindow
toFrame:(NSRect)newFrame
{
GdkMacosSurface *surface = gdk_surface;
GdkSurfaceState state = GDK_SURFACE (surface)->state;
if (state & GDK_SURFACE_STATE_MAXIMIZED)
{
lastMaximizedFrame = newFrame;
[self windowDidUnmaximize];
}
else
{
lastUnmaximizedFrame = [nsWindow frame];
gdk_synthesize_surface_state (GDK_SURFACE (gdk_surface), 0, GDK_SURFACE_STATE_MAXIMIZED);
}
inMaximizeTransition = YES;
return YES;
}
-(void)windowDidEndLiveResize:(NSNotification *)aNotification
{
gboolean maximized = GDK_SURFACE (gdk_surface)->state & GDK_SURFACE_STATE_MAXIMIZED;
inMaximizeTransition = NO;
/* Even if this is CSD, we want to be opaque while maximized
* to speed up compositing by allowing the display server to
* avoid costly blends.
*/
if (maximized)
[self setOpaque:YES];
}
-(NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)proposedSize
{
return [[window screen] frame].size;
}
-(void)windowWillEnterFullScreen:(NSNotification *)aNotification
{
lastUnfullscreenFrame = [self frame];
}
-(void)windowWillExitFullScreen:(NSNotification *)aNotification
{
[self setFrame:lastUnfullscreenFrame display:YES];
}
-(void)windowDidExitFullScreen:(NSNotification *)aNotification
{
}
-(void)windowDidChangeScreen:(NSNotification *)aNotification
{
_gdk_macos_surface_monitor_changed (gdk_surface);
}
-(void)setGdkSurface:(GdkMacosSurface *)surface
{
self->gdk_surface = surface;
}
-(void)setDecorated:(BOOL)decorated
{
NSWindowStyleMask style_mask = [self styleMask];
[self setHasShadow:decorated];
if (decorated)
style_mask |= NSWindowStyleMaskTitled;
else
style_mask &= ~NSWindowStyleMaskTitled;
[self setStyleMask:style_mask];
}
-(GdkMacosSurface *)gdkSurface
{
return self->gdk_surface;
}
-(GdkMacosDisplay *)gdkDisplay
{
return GDK_MACOS_DISPLAY (GDK_SURFACE (self->gdk_surface)->display);
}
-(BOOL)movableByWindowBackground
{
return NO;
}
@end

View File

@ -0,0 +1,70 @@
/* GdkMacosWindow.h
*
* Copyright © 2020 Red Hat, Inc.
* Copyright © 2005-2007 Imendio AB
*
* 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#include <gdk/gdk.h>
#include "gdkmacosdisplay.h"
#include "gdkmacossurface.h"
#include "edgesnapping.h"
#define GDK_IS_MACOS_WINDOW(obj) ([obj isKindOfClass:[GdkMacosWindow class]])
@interface GdkMacosWindow : NSWindow {
GdkMacosSurface *gdk_surface;
BOOL inMove;
BOOL inShowOrHide;
BOOL initialPositionKnown;
/* Manually triggered move/resize (not by the window manager) */
BOOL inManualMove;
BOOL inManualResize;
BOOL inTrackManualResize;
NSPoint initialResizeLocation;
NSRect initialResizeFrame;
GdkSurfaceEdge resizeEdge;
EdgeSnapping snapping;
NSRect lastUnmaximizedFrame;
NSRect lastMaximizedFrame;
NSRect lastUnfullscreenFrame;
BOOL inMaximizeTransition;
}
-(void)beginManualMove;
-(void)beginManualResize:(GdkSurfaceEdge)edge;
-(void)hide;
-(BOOL)isInManualResizeOrMove;
-(BOOL)isInMove;
-(GdkMacosDisplay *)gdkDisplay;
-(GdkMacosSurface *)gdkSurface;
-(void)setGdkSurface:(GdkMacosSurface *)surface;
-(void)setStyleMask:(NSWindowStyleMask)styleMask;
-(void)showAndMakeKey:(BOOL)makeKey;
-(BOOL)trackManualMove;
-(BOOL)trackManualResize;
-(void)setDecorated:(BOOL)decorated;
@end

229
gdk/macos/edgesnapping.c Normal file
View File

@ -0,0 +1,229 @@
/* edgesnapping.c
*
* Copyright © 2020 Red Hat, Inc.
*
* 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include "gdkrectangle.h"
#include "edgesnapping.h"
#define LEAVE_THRESHOLD 3.0
#define ENTER_THRESHOLD 2.0
#define X1(r) ((r)->x)
#define X2(r) ((r)->x + (r)->width)
#define Y1(r) ((r)->y)
#define Y2(r) ((r)->y + (r)->height)
void
_edge_snapping_init (EdgeSnapping *self,
const GdkRectangle *geometry,
const GdkRectangle *workarea,
const GdkPoint *pointer_position,
const GdkRectangle *window)
{
g_assert (self != NULL);
g_assert (geometry != NULL);
g_assert (workarea != NULL);
g_assert (pointer_position != NULL);
self->geometry = *geometry;
self->workarea = *workarea;
self->last_pointer_position = *pointer_position;
self->pointer_offset_in_window.x = pointer_position->x - window->x;
self->pointer_offset_in_window.y = pointer_position->y - window->y;
}
static void
edge_snapping_constrain_left (EdgeSnapping *self,
int change,
const GdkRectangle *geometry,
GdkRectangle *window)
{
if (change < 0)
{
if (X1 (window) < X1 (geometry) &&
X1 (window) > X1 (geometry) - LEAVE_THRESHOLD &&
ABS (change) < LEAVE_THRESHOLD)
window->x = geometry->x;
}
/* We don't constrain when returning from left edge */
}
static void
edge_snapping_constrain_right (EdgeSnapping *self,
int change,
const GdkRectangle *geometry,
GdkRectangle *window)
{
if (change > 0)
{
if (X2 (window) > X2 (geometry) &&
X2 (window) < X2 (geometry) + LEAVE_THRESHOLD &&
ABS (change) < LEAVE_THRESHOLD)
window->x = X2 (geometry) - window->width;
}
/* We don't constrain when returning from right edge */
}
static void
edge_snapping_constrain_top (EdgeSnapping *self,
int change,
const GdkRectangle *geometry,
GdkRectangle *window)
{
if (change < 0)
{
if (Y1 (window) < Y1 (geometry))
window->y = geometry->y;
}
/* We don't constrain when returning from top edge */
}
static void
edge_snapping_constrain_bottom (EdgeSnapping *self,
int change,
const GdkRectangle *geometry,
GdkRectangle *window)
{
if (change > 0)
{
if (Y2 (window) > Y2 (geometry) &&
Y2 (window) < Y2 (geometry) + LEAVE_THRESHOLD &&
ABS (change) < LEAVE_THRESHOLD)
window->y = Y2 (geometry) - window->height;
}
else if (change < 0)
{
if (Y2 (window) < Y2 (geometry) &&
Y2 (window) > Y2 (geometry) - ENTER_THRESHOLD &&
ABS (change) < ENTER_THRESHOLD)
window->y = Y2 (geometry) - window->height;
}
}
static void
edge_snapping_constrain_horizontal (EdgeSnapping *self,
int change,
const GdkRectangle *geometry,
GdkRectangle *window)
{
g_assert (self != NULL);
g_assert (geometry != NULL);
g_assert (window != NULL);
g_assert (change != 0);
if (ABS (X1 (geometry) - X1 (window)) < ABS (X2 (geometry)) - ABS (X2 (window)))
edge_snapping_constrain_left (self, change, geometry, window);
else
edge_snapping_constrain_right (self, change, geometry, window);
}
static void
edge_snapping_constrain_vertical (EdgeSnapping *self,
int change,
const GdkRectangle *geometry,
GdkRectangle *window,
gboolean bottom_only)
{
g_assert (self != NULL);
g_assert (geometry != NULL);
g_assert (window != NULL);
g_assert (change != 0);
if (!bottom_only &&
ABS (Y1 (geometry) - Y1 (window)) < ABS (Y2 (geometry)) - ABS (Y2 (window)))
edge_snapping_constrain_top (self, change, geometry, window);
else
edge_snapping_constrain_bottom (self, change, geometry, window);
}
void
_edge_snapping_motion (EdgeSnapping *self,
const GdkPoint *pointer_position,
GdkRectangle *window)
{
GdkRectangle new_window;
GdkRectangle overlap;
GdkPoint change;
g_assert (self != NULL);
g_assert (pointer_position != NULL);
change.x = pointer_position->x - self->last_pointer_position.x;
change.y = pointer_position->y - self->last_pointer_position.y;
self->last_pointer_position = *pointer_position;
window->x += change.x;
window->y += change.y;
new_window = *window;
/* First constrain horizontal */
if (change.x)
{
edge_snapping_constrain_horizontal (self, change.x, &self->workarea, &new_window);
if (gdk_rectangle_equal (&new_window, window))
edge_snapping_constrain_horizontal (self, change.x, &self->geometry, &new_window);
}
/* Now constrain veritcally */
if (change.y)
{
edge_snapping_constrain_vertical (self, change.y, &self->workarea, &new_window, FALSE);
if (new_window.y == window->y)
edge_snapping_constrain_vertical (self, change.y, &self->geometry, &new_window, TRUE);
}
/* If the window is not placed in the monitor at all, then we need to
* just move the window onto the new screen using the original offset
* of the pointer within the window.
*/
if (!gdk_rectangle_intersect (&self->geometry, &new_window, &overlap))
{
new_window.x = pointer_position->x - self->pointer_offset_in_window.x;
new_window.y = pointer_position->y - self->pointer_offset_in_window.y;
}
/* And finally make sure we aren't underneath the top bar of the
* particular monitor.
*/
if (Y1 (&new_window) < Y1 (&self->workarea))
new_window.y = self->workarea.y;
*window = new_window;
}
void
_edge_snapping_set_monitor (EdgeSnapping *self,
const GdkRectangle *geometry,
const GdkRectangle *workarea)
{
g_assert (self != NULL);
g_assert (geometry != NULL);
g_assert (workarea != NULL);
self->geometry = *geometry;
self->workarea = *workarea;
}

50
gdk/macos/edgesnapping.h Normal file
View File

@ -0,0 +1,50 @@
/* edgesnapping.h
*
* Copyright © 2020 Red Hat, Inc.
*
* 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __EDGE_SNAPPING_H__
#define __EDGE_SNAPPING_H__
#include "gdktypes.h"
G_BEGIN_DECLS
typedef struct
{
GdkRectangle geometry;
GdkRectangle workarea;
GdkPoint last_pointer_position;
GdkPoint pointer_offset_in_window;
} EdgeSnapping;
void _edge_snapping_init (EdgeSnapping *self,
const GdkRectangle *geometry,
const GdkRectangle *workarea,
const GdkPoint *pointer_position,
const GdkRectangle *window);
void _edge_snapping_motion (EdgeSnapping *self,
const GdkPoint *pointer_position,
GdkRectangle *window);
void _edge_snapping_set_monitor (EdgeSnapping *self,
const GdkRectangle *geometry,
const GdkRectangle *workarea);
G_END_DECLS
#endif /* __EDGE_SNAPPING_H__ */

View File

@ -0,0 +1,254 @@
/* 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 <AppKit/AppKit.h>
#include <mach/mach_time.h>
#include "gdkdisplaylinksource.h"
#include "gdkmacoseventsource-private.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: NSEventTypeApplicationDefined
location: NSZeroPoint
modifierFlags: 0
timestamp: 0
windowNumber: 0
context: nil
subtype: GDK_MACOS_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;
impl->refresh_rate = 1.0 / period * 1000L;
/*
* 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;
}

View File

@ -0,0 +1,49 @@
/* 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;
guint refresh_rate;
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 */

32
gdk/macos/gdkmacos.h Normal file
View File

@ -0,0 +1,32 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_H__
#define __GDK_MACOS_H__
#include <gdk/gdk.h>
#include "gdkmacosdevice.h"
#include "gdkmacosdisplay.h"
#include "gdkmacosglcontext.h"
#include "gdkmacoskeymap.h"
#include "gdkmacosmonitor.h"
#include "gdkmacossurface.h"
#endif /* __GDK_MACOS_H__ */

View File

@ -0,0 +1,38 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_CAIRO_CONTEXT_PRIVATE_H__
#define __GDK_MACOS_CAIRO_CONTEXT_PRIVATE_H__
#include "gdkcairocontextprivate.h"
G_BEGIN_DECLS
typedef struct _GdkMacosCairoContext GdkMacosCairoContext;
typedef struct _GdkMacosCairoContextClass GdkMacosCairoContextClass;
#define GDK_TYPE_MACOS_CAIRO_CONTEXT (_gdk_macos_cairo_context_get_type())
#define GDK_MACOS_CAIRO_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_CAIRO_CONTEXT, GdkMacosCairoContext))
#define GDK_IS_MACOS_CAIRO_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_CAIRO_CONTEXT))
GType _gdk_macos_cairo_context_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GDK_MACOS_CAIRO_CONTEXT_PRIVATE_H__ */

View File

@ -0,0 +1,155 @@
/*
* Copyright © 2016 Benjamin Otte
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include "gdkconfig.h"
#include <CoreGraphics/CoreGraphics.h>
#include <cairo-quartz.h>
#import "GdkMacosCairoView.h"
#include "gdkmacoscairocontext-private.h"
#include "gdkmacossurface-private.h"
struct _GdkMacosCairoContext
{
GdkCairoContext parent_instance;
cairo_surface_t *window_surface;
};
struct _GdkMacosCairoContextClass
{
GdkCairoContextClass parent_class;
};
G_DEFINE_TYPE (GdkMacosCairoContext, _gdk_macos_cairo_context, GDK_TYPE_CAIRO_CONTEXT)
static cairo_surface_t *
create_cairo_surface_for_surface (GdkSurface *surface)
{
cairo_surface_t *cairo_surface;
int scale;
int width;
int height;
g_assert (GDK_IS_MACOS_SURFACE (surface));
scale = gdk_surface_get_scale_factor (surface);
width = scale * gdk_surface_get_width (surface);
height = scale * gdk_surface_get_height (surface);
cairo_surface = cairo_quartz_surface_create (CAIRO_FORMAT_ARGB32, width, height);
if (cairo_surface != NULL)
cairo_surface_set_device_scale (cairo_surface, scale, scale);
return cairo_surface;
}
static cairo_t *
_gdk_macos_cairo_context_cairo_create (GdkCairoContext *cairo_context)
{
GdkMacosCairoContext *self = (GdkMacosCairoContext *)cairo_context;
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
return cairo_create (self->window_surface);
}
static void
_gdk_macos_cairo_context_begin_frame (GdkDrawContext *draw_context,
cairo_region_t *region)
{
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
GdkSurface *surface;
NSWindow *nswindow;
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
surface = gdk_draw_context_get_surface (draw_context);
nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface));
if (self->window_surface == NULL)
{
self->window_surface = create_cairo_surface_for_surface (surface);
}
else
{
if (![nswindow isOpaque])
{
cairo_t *cr = cairo_create (self->window_surface);
gdk_cairo_region (cr, region);
cairo_set_source_rgba (cr, 0, 0, 0, 0);
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
cairo_fill (cr);
cairo_destroy (cr);
}
}
}
static void
_gdk_macos_cairo_context_end_frame (GdkDrawContext *draw_context,
cairo_region_t *painted)
{
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
GdkSurface *surface;
NSView *nsview;
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
g_assert (self->window_surface != NULL);
surface = gdk_draw_context_get_surface (draw_context);
nsview = _gdk_macos_surface_get_view (GDK_MACOS_SURFACE (surface));
if (GDK_IS_MACOS_CAIRO_VIEW (nsview))
[(GdkMacosCairoView *)nsview setCairoSurface:self->window_surface
withDamage:painted];
}
static void
_gdk_macos_cairo_context_surface_resized (GdkDrawContext *draw_context)
{
GdkMacosCairoContext *self = (GdkMacosCairoContext *)draw_context;
g_assert (GDK_IS_MACOS_CAIRO_CONTEXT (self));
g_clear_pointer (&self->window_surface, cairo_surface_destroy);
}
static void
_gdk_macos_cairo_context_class_init (GdkMacosCairoContextClass *klass)
{
GdkCairoContextClass *cairo_context_class = GDK_CAIRO_CONTEXT_CLASS (klass);
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
draw_context_class->begin_frame = _gdk_macos_cairo_context_begin_frame;
draw_context_class->end_frame = _gdk_macos_cairo_context_end_frame;
draw_context_class->surface_resized = _gdk_macos_cairo_context_surface_resized;
cairo_context_class->cairo_create = _gdk_macos_cairo_context_cairo_create;
}
static void
_gdk_macos_cairo_context_init (GdkMacosCairoContext *self)
{
}

View File

@ -0,0 +1,54 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_CLIPBOARD_PRIVATE_H__
#define __GDK_MACOS_CLIPBOARD_PRIVATE_H__
#include <AppKit/AppKit.h>
#include "gdkclipboardprivate.h"
#include "gdkmacosdisplay-private.h"
G_BEGIN_DECLS
#define GDK_TYPE_MACOS_CLIPBOARD (_gdk_macos_clipboard_get_type())
G_DECLARE_FINAL_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK, MACOS_CLIPBOARD, GdkClipboard)
GdkClipboard *_gdk_macos_clipboard_new (GdkMacosDisplay *display);
void _gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self);
NSPasteboardType _gdk_macos_clipboard_to_ns_type (const char *mime_type,
NSPasteboardType *alternate);
const char *_gdk_macos_clipboard_from_ns_type (NSPasteboardType ns_type);
@interface GdkMacosClipboardDataProvider : NSObject <NSPasteboardItemDataProvider>
{
GCancellable *cancellable;
GdkClipboard *clipboard;
char **mimeTypes;
}
-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
-(NSArray<NSPasteboardType> *)types;
@end
G_END_DECLS
#endif /* __GDK_MACOS_CLIPBOARD_PRIVATE_H__ */

View File

@ -0,0 +1,576 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include <glib/gi18n.h>
#include "gdkmacosclipboard-private.h"
#include "gdkmacosutils-private.h"
struct _GdkMacosClipboard
{
GdkClipboard parent_instance;
NSPasteboard *pasteboard;
NSInteger last_change_count;
};
typedef struct
{
GMemoryOutputStream *stream;
NSPasteboardItem *item;
NSPasteboardType type;
GMainContext *main_context;
guint done : 1;
} WriteRequest;
G_DEFINE_TYPE (GdkMacosClipboard, _gdk_macos_clipboard, GDK_TYPE_CLIPBOARD)
static void
write_request_free (WriteRequest *wr)
{
g_clear_pointer (&wr->main_context, g_main_context_unref);
g_clear_object (&wr->stream);
[wr->item release];
g_slice_free (WriteRequest, wr);
}
const char *
_gdk_macos_clipboard_from_ns_type (NSPasteboardType type)
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if ([type isEqualToString:NSPasteboardTypeString] ||
[type isEqualToString:NSStringPboardType])
return g_intern_string ("text/plain;charset=utf-8");
else if ([type isEqualToString:NSPasteboardTypeURL] ||
[type isEqualToString:NSPasteboardTypeFileURL])
return g_intern_string ("text/uri-list");
else if ([type isEqualToString:NSPasteboardTypeColor])
return g_intern_string ("application/x-color");
else if ([type isEqualToString:NSPasteboardTypeTIFF])
return g_intern_string ("image/tiff");
else if ([type isEqualToString:NSPasteboardTypePNG])
return g_intern_string ("image/png");
G_GNUC_END_IGNORE_DEPRECATIONS;
return NULL;
}
NSPasteboardType
_gdk_macos_clipboard_to_ns_type (const char *mime_type,
NSPasteboardType *alternate)
{
if (alternate)
*alternate = NULL;
if (g_strcmp0 (mime_type, "text/plain;charset=utf-8") == 0)
{
return NSPasteboardTypeString;
}
else if (g_strcmp0 (mime_type, "text/uri-list") == 0)
{
if (alternate)
*alternate = NSPasteboardTypeURL;
return NSPasteboardTypeFileURL;
}
else if (g_strcmp0 (mime_type, "application/x-color") == 0)
{
return NSPasteboardTypeColor;
}
else if (g_strcmp0 (mime_type, "image/tiff") == 0)
{
return NSPasteboardTypeTIFF;
}
else if (g_strcmp0 (mime_type, "image/png") == 0)
{
return NSPasteboardTypePNG;
}
return nil;
}
static void
populate_content_formats (GdkContentFormatsBuilder *builder,
NSPasteboardType type)
{
const char *mime_type;
g_return_if_fail (builder != NULL);
g_return_if_fail (type != NULL);
mime_type = _gdk_macos_clipboard_from_ns_type (type);
if (mime_type != NULL)
gdk_content_formats_builder_add_mime_type (builder, mime_type);
}
static GdkContentFormats *
load_offer_formats (GdkMacosClipboard *self)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkContentFormatsBuilder *builder;
GdkContentFormats *formats;
g_assert (GDK_IS_MACOS_CLIPBOARD (self));
builder = gdk_content_formats_builder_new ();
for (NSPasteboardType type in [self->pasteboard types])
populate_content_formats (builder, type);
formats = gdk_content_formats_builder_free_to_formats (builder);
GDK_END_MACOS_ALLOC_POOL;
return g_steal_pointer (&formats);
}
static void
_gdk_macos_clipboard_load_contents (GdkMacosClipboard *self)
{
GdkContentFormats *formats;
NSInteger change_count;
g_assert (GDK_IS_MACOS_CLIPBOARD (self));
change_count = [self->pasteboard changeCount];
formats = load_offer_formats (self);
gdk_clipboard_claim_remote (GDK_CLIPBOARD (self), formats);
gdk_content_formats_unref (formats);
self->last_change_count = change_count;
}
static GInputStream *
create_stream_from_nsdata (NSData *data)
{
const guint8 *bytes = [data bytes];
gsize len = [data length];
return g_memory_input_stream_new_from_data (g_memdup (bytes, len), len, g_free);
}
static void
_gdk_macos_clipboard_read_async (GdkClipboard *clipboard,
GdkContentFormats *formats,
int io_priority,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkMacosClipboard *self = (GdkMacosClipboard *)clipboard;
GdkContentFormats *offer_formats = NULL;
const char *mime_type;
GInputStream *stream = NULL;
GTask *task = NULL;
g_assert (GDK_IS_MACOS_CLIPBOARD (self));
g_assert (formats != NULL);
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, _gdk_macos_clipboard_read_async);
g_task_set_priority (task, io_priority);
offer_formats = load_offer_formats (GDK_MACOS_CLIPBOARD (clipboard));
mime_type = gdk_content_formats_match_mime_type (formats, offer_formats);
if (mime_type == NULL)
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
"%s",
_("No compatible transfer format found"));
goto cleanup;
}
if (strcmp (mime_type, "text/plain;charset=utf-8") == 0)
{
NSString *nsstr = [self->pasteboard stringForType:NSPasteboardTypeString];
if (nsstr != NULL)
{
const char *str = [nsstr UTF8String];
stream = g_memory_input_stream_new_from_data (g_strdup (str),
strlen (str) + 1,
g_free);
}
}
else if (strcmp (mime_type, "text/uri-list") == 0)
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if ([[self->pasteboard types] containsObject:NSPasteboardTypeFileURL])
{
GString *str = g_string_new (NULL);
NSArray *files = [self->pasteboard propertyListForType:NSFilenamesPboardType];
gsize n_files = [files count];
char *data;
guint len;
for (gsize i = 0; i < n_files; ++i)
{
NSString* uriString = [files objectAtIndex:i];
uriString = [@"file://" stringByAppendingString:uriString];
uriString = [uriString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
g_string_append_printf (str,
"%s\r\n",
[uriString cStringUsingEncoding:NSUTF8StringEncoding]);
}
len = str->len;
data = g_string_free (str, FALSE);
stream = g_memory_input_stream_new_from_data (data, len, g_free);
}
G_GNUC_END_IGNORE_DEPRECATIONS;
}
else if (strcmp (mime_type, "application/x-color") == 0)
{
NSColorSpace *colorspace;
NSColor *nscolor;
guint16 color[4];
colorspace = [NSColorSpace genericRGBColorSpace];
nscolor = [[NSColor colorFromPasteboard:self->pasteboard]
colorUsingColorSpace:colorspace];
color[0] = 0xffff * [nscolor redComponent];
color[1] = 0xffff * [nscolor greenComponent];
color[2] = 0xffff * [nscolor blueComponent];
color[3] = 0xffff * [nscolor alphaComponent];
stream = g_memory_input_stream_new_from_data (g_memdup (&color, sizeof color),
sizeof color,
g_free);
}
else if (strcmp (mime_type, "image/tiff") == 0)
{
NSData *data = [self->pasteboard dataForType:NSPasteboardTypeTIFF];
stream = create_stream_from_nsdata (data);
}
else if (strcmp (mime_type, "image/png") == 0)
{
NSData *data = [self->pasteboard dataForType:NSPasteboardTypePNG];
stream = create_stream_from_nsdata (data);
}
if (stream != NULL)
{
g_task_set_task_data (task, g_strdup (mime_type), g_free);
g_task_return_pointer (task, g_steal_pointer (&stream), g_object_unref);
}
else
{
g_task_return_new_error (task,
G_IO_ERROR,
G_IO_ERROR_FAILED,
_("Failed to decode contents with mime-type of '%s'"),
mime_type);
}
cleanup:
g_clear_object (&task);
g_clear_pointer (&offer_formats, gdk_content_formats_unref);
GDK_END_MACOS_ALLOC_POOL;
}
static GInputStream *
_gdk_macos_clipboard_read_finish (GdkClipboard *clipboard,
GAsyncResult *result,
const char **out_mime_type,
GError **error)
{
GTask *task = (GTask *)result;
g_assert (GDK_IS_MACOS_CLIPBOARD (clipboard));
g_assert (G_IS_TASK (task));
if (out_mime_type != NULL)
*out_mime_type = g_strdup (g_task_get_task_data (task));
return g_task_propagate_pointer (task, error);
}
static void
_gdk_macos_clipboard_send_to_pasteboard (GdkMacosClipboard *self,
GdkContentProvider *content)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkMacosClipboardDataProvider *dataProvider;
GdkContentFormats *serializable;
NSPasteboardItem *item;
const char * const *mime_types;
gsize n_mime_types;
g_return_if_fail (GDK_IS_MACOS_CLIPBOARD (self));
g_return_if_fail (GDK_IS_CONTENT_PROVIDER (content));
serializable = gdk_content_provider_ref_storable_formats (content);
serializable = gdk_content_formats_union_serialize_mime_types (serializable);
mime_types = gdk_content_formats_get_mime_types (serializable, &n_mime_types);
dataProvider = [[GdkMacosClipboardDataProvider alloc] initClipboard:GDK_CLIPBOARD (self)
mimetypes:mime_types];
item = [[NSPasteboardItem alloc] init];
[item setDataProvider:dataProvider forTypes:[dataProvider types]];
[self->pasteboard clearContents];
if ([self->pasteboard writeObjects:[NSArray arrayWithObject:item]] == NO)
g_warning ("Failed to write object to pasteboard");
self->last_change_count = [self->pasteboard changeCount];
g_clear_pointer (&serializable, gdk_content_formats_unref);
GDK_END_MACOS_ALLOC_POOL;
}
static gboolean
_gdk_macos_clipboard_claim (GdkClipboard *clipboard,
GdkContentFormats *formats,
gboolean local,
GdkContentProvider *provider)
{
GdkMacosClipboard *self = (GdkMacosClipboard *)clipboard;
gboolean ret;
g_assert (GDK_IS_CLIPBOARD (clipboard));
g_assert (formats != NULL);
g_assert (!provider || GDK_IS_CONTENT_PROVIDER (provider));
ret = GDK_CLIPBOARD_CLASS (_gdk_macos_clipboard_parent_class)->claim (clipboard, formats, local, provider);
if (local)
_gdk_macos_clipboard_send_to_pasteboard (self, provider);
return ret;
}
static void
_gdk_macos_clipboard_constructed (GObject *object)
{
GdkMacosClipboard *self = (GdkMacosClipboard *)object;
if (self->pasteboard == nil)
self->pasteboard = [[NSPasteboard generalPasteboard] retain];
G_OBJECT_CLASS (_gdk_macos_clipboard_parent_class)->constructed (object);
}
static void
_gdk_macos_clipboard_finalize (GObject *object)
{
GdkMacosClipboard *self = (GdkMacosClipboard *)object;
if (self->pasteboard != nil)
{
[self->pasteboard release];
self->pasteboard = nil;
}
G_OBJECT_CLASS (_gdk_macos_clipboard_parent_class)->finalize (object);
}
static void
_gdk_macos_clipboard_class_init (GdkMacosClipboardClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkClipboardClass *clipboard_class = GDK_CLIPBOARD_CLASS (klass);
object_class->constructed = _gdk_macos_clipboard_constructed;
object_class->finalize = _gdk_macos_clipboard_finalize;
clipboard_class->claim = _gdk_macos_clipboard_claim;
clipboard_class->read_async = _gdk_macos_clipboard_read_async;
clipboard_class->read_finish = _gdk_macos_clipboard_read_finish;
}
static void
_gdk_macos_clipboard_init (GdkMacosClipboard *self)
{
}
GdkClipboard *
_gdk_macos_clipboard_new (GdkMacosDisplay *display)
{
GdkMacosClipboard *self;
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
self = g_object_new (GDK_TYPE_MACOS_CLIPBOARD,
"display", display,
NULL);
_gdk_macos_clipboard_load_contents (self);
return GDK_CLIPBOARD (self);
}
void
_gdk_macos_clipboard_check_externally_modified (GdkMacosClipboard *self)
{
g_return_if_fail (GDK_IS_MACOS_CLIPBOARD (self));
if ([self->pasteboard changeCount] != self->last_change_count)
_gdk_macos_clipboard_load_contents (self);
}
@implementation GdkMacosClipboardDataProvider
-(id)initClipboard:(GdkClipboard *)gdkClipboard mimetypes:(const char * const *)mime_types;
{
[super init];
self->mimeTypes = g_strdupv ((char **)mime_types);
self->clipboard = g_object_ref (gdkClipboard);
return self;
}
-(void)dealloc
{
g_cancellable_cancel (self->cancellable);
g_clear_pointer (&self->mimeTypes, g_strfreev);
g_clear_object (&self->clipboard);
g_clear_object (&self->cancellable);
[super dealloc];
}
-(void)pasteboardFinishedWithDataProvider:(NSPasteboard *)pasteboard
{
g_clear_object (&self->clipboard);
}
-(NSArray<NSPasteboardType> *)types
{
NSMutableArray *ret = [[NSMutableArray alloc] init];
for (guint i = 0; self->mimeTypes[i]; i++)
{
const char *mime_type = self->mimeTypes[i];
NSPasteboardType type;
NSPasteboardType alternate = nil;
if ((type = _gdk_macos_clipboard_to_ns_type (mime_type, &alternate)))
{
[ret addObject:type];
if (alternate)
[ret addObject:alternate];
}
}
return g_steal_pointer (&ret);
}
static void
on_data_ready_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkClipboard *clipboard = (GdkClipboard *)object;
WriteRequest *wr = user_data;
GError *error = NULL;
NSData *data = nil;
g_assert (GDK_IS_CLIPBOARD (clipboard));
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (wr != NULL);
g_assert (G_IS_MEMORY_OUTPUT_STREAM (wr->stream));
g_assert ([wr->item isKindOfClass:[NSPasteboardItem class]]);
if (gdk_clipboard_write_finish (clipboard, result, &error))
{
gsize size;
gpointer bytes;
g_output_stream_close (G_OUTPUT_STREAM (wr->stream), NULL, NULL);
size = g_memory_output_stream_get_size (wr->stream);
bytes = g_memory_output_stream_steal_data (wr->stream);
data = [[NSData alloc] initWithBytesNoCopy:bytes
length:size
deallocator:^(void *alloc, NSUInteger length) { g_free (alloc); }];
}
else
{
g_warning ("Failed to serialize clipboard contents: %s",
error->message);
g_clear_error (&error);
}
[wr->item setData:data forType:wr->type];
wr->done = TRUE;
GDK_END_MACOS_ALLOC_POOL;
}
-(void) pasteboard:(NSPasteboard *)pasteboard
item:(NSPasteboardItem *)item
provideDataForType:(NSPasteboardType)type
{
const char *mime_type = _gdk_macos_clipboard_from_ns_type (type);
GMainContext *main_context = g_main_context_default ();
WriteRequest *wr;
if (self->clipboard == NULL || mime_type == NULL)
{
[item setData:[NSData data] forType:type];
return;
}
wr = g_slice_new0 (WriteRequest);
wr->item = [item retain];
wr->stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new_resizable ());
wr->type = type;
wr->main_context = g_main_context_ref (main_context);
wr->done = FALSE;
gdk_clipboard_write_async (self->clipboard,
mime_type,
G_OUTPUT_STREAM (wr->stream),
G_PRIORITY_DEFAULT,
self->cancellable,
on_data_ready_cb,
wr);
/* We're forced to provide data synchronously via this API
* so we must block on the main loop. Using another main loop
* than the default tends to get us locked up here, so that is
* what we'll do for now.
*/
while (!wr->done)
g_main_context_iteration (wr->main_context, TRUE);
write_request_free (wr);
}
@end

View File

@ -1,7 +1,7 @@
/* gdkdnd-quartz.h
/* gdkmacoscursor-private.h
*
* Copyright (C) 2005 Imendio AB
* Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
* Copyright (C) 2005-2007 Imendio AB
* Copyright (C) 2020 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -17,29 +17,16 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_DND__
#define __GDK_QUARTZ_DND__
#include <gdkdndprivate.h>
#include "gdkquartzdnd.h"
#ifndef __GDK_MACOS_CURSOR_PRIVATE_H__
#define __GDK_MACOS_CURSOR_PRIVATE_H__
#include <AppKit/AppKit.h>
#include <gdk/gdk.h>
G_BEGIN_DECLS
struct _GdkQuartzDragContext
{
GdkDragContext context;
id <NSDraggingInfo> dragging_info;
GdkDevice *device;
};
struct _GdkQuartzDragContextClass
{
GdkDragContextClass context_class;
};
NSCursor *_gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor);
G_END_DECLS
#endif /* __GDK_QUARTZ_DND__ */
#endif /* __GDK_MACOS_CURSOR_PRIVATE_H__ */

181
gdk/macos/gdkmacoscursor.c Normal file
View File

@ -0,0 +1,181 @@
/* gdkcursor-macos.c
*
* Copyright (C) 2005-2007 Imendio AB
* Copyright (C) 2020 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <string.h>
#include "gdkmacoscursor-private.h"
/* OS X only exports a number of cursor types in its public NSCursor interface.
* By overriding the private _coreCursorType method, we can tell OS X to load
* one of its internal cursors instead (since cursor images are loaded on demand
* instead of in advance). WebKit does this too.
*/
@interface gdkCoreCursor : NSCursor {
@private
int type;
BOOL override;
}
@end
@implementation gdkCoreCursor
- (long long)_coreCursorType
{
if (self->override)
return self->type;
return [super _coreCursorType];
}
#define CUSTOM_CURSOR_CTOR(name, id) \
+ (gdkCoreCursor *)name \
{ \
gdkCoreCursor *obj; \
obj = [self new]; \
if (obj) { \
obj->override = YES; \
obj->type = id; \
} \
return obj; \
}
CUSTOM_CURSOR_CTOR(gdkHelpCursor, 40)
CUSTOM_CURSOR_CTOR(gdkProgressCursor, 4)
/* TODO OS X doesn't seem to have a way to get this. There is an undocumented
* method +[NSCursor _waitCursor], but it doesn't actually return this cursor,
* but rather some odd low-quality non-animating version of this cursor. Use
* the progress cursor instead for now.
*/
CUSTOM_CURSOR_CTOR(gdkWaitCursor, 4)
CUSTOM_CURSOR_CTOR(gdkAliasCursor, 2)
CUSTOM_CURSOR_CTOR(gdkMoveCursor, 39)
/* TODO OS X doesn't seem to provide one; copy the move cursor for now
* since it looks similar to what we want. */
CUSTOM_CURSOR_CTOR(gdkAllScrollCursor, 39)
CUSTOM_CURSOR_CTOR(gdkNEResizeCursor, 29)
CUSTOM_CURSOR_CTOR(gdkNWResizeCursor, 33)
CUSTOM_CURSOR_CTOR(gdkSEResizeCursor, 35)
CUSTOM_CURSOR_CTOR(gdkSWResizeCursor, 37)
CUSTOM_CURSOR_CTOR(gdkEWResizeCursor, 28)
CUSTOM_CURSOR_CTOR(gdkNSResizeCursor, 32)
CUSTOM_CURSOR_CTOR(gdkNESWResizeCursor, 30)
CUSTOM_CURSOR_CTOR(gdkNWSEResizeCursor, 34)
CUSTOM_CURSOR_CTOR(gdkZoomInCursor, 42)
CUSTOM_CURSOR_CTOR(gdkZoomOutCursor, 43)
#undef CUSTOM_CURSOR_CTOR
@end
struct CursorsByName {
const gchar *name;
NSString *selector;
};
static const struct CursorsByName cursors_by_name[] = {
/* Link & Status */
{ "context-menu", @"contextualMenuCursor" },
{ "help", @"gdkHelpCursor" },
{ "pointer", @"pointingHandCursor" },
{ "progress", @"gdkProgressCursor" },
{ "wait", @"gdkWaitCursor" },
/* Selection */
{ "cell", @"crosshairCursor" },
{ "crosshair", @"crosshairCursor" },
{ "text", @"IBeamCursor" },
{ "vertical-text", @"IBeamCursorForVerticalLayout" },
/* Drag & Drop */
{ "alias", @"gdkAliasCursor" },
{ "copy", @"dragCopyCursor" },
{ "move", @"gdkMoveCursor" },
{ "no-drop", @"operationNotAllowedCursor" },
{ "not-allowed", @"operationNotAllowedCursor" },
{ "grab", @"openHandCursor" },
{ "grabbing", @"closedHandCursor" },
/* Resize & Scrolling */
{ "all-scroll", @"gdkAllScrollCursor" },
{ "col-resize", @"resizeLeftRightCursor" },
{ "row-resize", @"resizeUpDownCursor" },
/* Undocumented cursors to match native resizing */
{ "e-resize", @"_windowResizeEastWestCursor" },
{ "w-resize", @"_windowResizeEastWestCursor" },
{ "n-resize", @"_windowResizeNorthSouthCursor" },
{ "s-resize", @"_windowResizeNorthSouthCursor" },
{ "ne-resize", @"gdkNEResizeCursor" },
{ "nw-resize", @"gdkNWResizeCursor" },
{ "se-resize", @"gdkSEResizeCursor" },
{ "sw-resize", @"gdkSWResizeCursor" },
{ "ew-resize", @"gdkEWResizeCursor" },
{ "ns-resize", @"gdkNSResizeCursor" },
{ "nesw-resize", @"gdkNESWResizeCursor" },
{ "nwse-resize", @"gdkNWSEResizeCursor" },
/* Zoom */
{ "zoom-in", @"gdkZoomInCursor" },
{ "zoom-out", @"gdkZoomOutCursor" },
};
static NSCursor *
create_blank_cursor (void)
{
NSCursor *nscursor;
NSImage *nsimage;
NSSize size = { 1.0, 1.0 };
nsimage = [[NSImage alloc] initWithSize:size];
nscursor = [[NSCursor alloc] initWithImage:nsimage
hotSpot:NSMakePoint(0.0, 0.0)];
[nsimage release];
return nscursor;
}
NSCursor *
_gdk_macos_cursor_get_ns_cursor (GdkCursor *cursor)
{
const char *name = NULL;
NSCursor *nscursor;
SEL selector = @selector(arrowCursor);
g_return_val_if_fail (!cursor || GDK_IS_CURSOR (cursor), NULL);
if (cursor != NULL)
name = gdk_cursor_get_name (cursor);
if (name == NULL)
goto load_cursor;
if (strcmp (name, "none") == 0)
return create_blank_cursor ();
for (guint i = 0; i < G_N_ELEMENTS (cursors_by_name); i++)
{
if (strcmp (cursors_by_name[i].name, name) == 0)
{
selector = NSSelectorFromString (cursors_by_name[i].selector);
break;
}
}
load_cursor:
nscursor = [[gdkCoreCursor class] performSelector:selector];
[nscursor retain];
return nscursor;
}

208
gdk/macos/gdkmacosdevice.c Normal file
View File

@ -0,0 +1,208 @@
/*
* Copyright 2009 Carlos Garnacho <carlosg@gnome.org>
* Copyright 2010 Kristian Rietveld <kris@gtk.org>
* Copyright 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include <gdk/gdk.h>
#include "gdkdeviceprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkmacoscursor-private.h"
#include "gdkmacosdevice.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacossurface-private.h"
struct _GdkMacosDevice
{
GdkDevice parent_instance;
};
struct _GdkMacosDeviceClass
{
GdkDeviceClass parent_class;
};
G_DEFINE_TYPE (GdkMacosDevice, gdk_macos_device, GDK_TYPE_DEVICE)
static void
gdk_macos_device_set_surface_cursor (GdkDevice *device,
GdkSurface *surface,
GdkCursor *cursor)
{
NSCursor *nscursor;
g_assert (GDK_IS_MACOS_DEVICE (device));
g_assert (GDK_IS_MACOS_SURFACE (surface));
g_assert (!cursor || GDK_IS_CURSOR (cursor));
nscursor = _gdk_macos_cursor_get_ns_cursor (cursor);
if (nscursor != NULL)
{
[nscursor set];
[nscursor release];
}
}
static GdkSurface *
gdk_macos_device_surface_at_position (GdkDevice *device,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *state)
{
GdkMacosDisplay *display;
GdkMacosSurface *surface;
NSPoint point;
gint x;
gint y;
g_assert (GDK_IS_MACOS_DEVICE (device));
g_assert (win_x != NULL);
g_assert (win_y != NULL);
point = [NSEvent mouseLocation];
display = GDK_MACOS_DISPLAY (gdk_device_get_display (device));
if (state != NULL)
*state = (_gdk_macos_display_get_current_keyboard_modifiers (display) |
_gdk_macos_display_get_current_mouse_modifiers (display));
surface = _gdk_macos_display_get_surface_at_display_coords (display, point.x, point.y, &x, &y);
*win_x = x;
*win_y = y;
return GDK_SURFACE (surface);
}
static GdkGrabStatus
gdk_macos_device_grab (GdkDevice *device,
GdkSurface *window,
gboolean owner_events,
GdkEventMask event_mask,
GdkSurface *confine_to,
GdkCursor *cursor,
guint32 time_)
{
/* Should remain empty */
return GDK_GRAB_SUCCESS;
}
static void
gdk_macos_device_ungrab (GdkDevice *device,
guint32 time_)
{
GdkMacosDevice *self = (GdkMacosDevice *)device;
GdkDeviceGrabInfo *grab;
GdkDisplay *display;
g_assert (GDK_IS_MACOS_DEVICE (self));
display = gdk_device_get_display (device);
grab = _gdk_display_get_last_device_grab (display, device);
if (grab != NULL)
grab->serial_end = 0;
_gdk_display_device_grab_update (display, device, device, 0);
}
static void
gdk_macos_device_get_state (GdkDevice *device,
GdkSurface *surface,
gdouble *axes,
GdkModifierType *mask)
{
gdouble x_pos, y_pos;
g_assert (GDK_IS_MACOS_DEVICE (device));
g_assert (GDK_IS_MACOS_SURFACE (surface));
gdk_surface_get_device_position (surface, device, &x_pos, &y_pos, mask);
if (axes != NULL)
{
axes[0] = x_pos;
axes[1] = y_pos;
}
}
static void
gdk_macos_device_query_state (GdkDevice *device,
GdkSurface *surface,
GdkSurface **child_surface,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask)
{
GdkDisplay *display;
NSPoint point;
int sx = 0;
int sy = 0;
int x_tmp;
int y_tmp;
g_assert (GDK_IS_MACOS_DEVICE (device));
g_assert (!surface || GDK_IS_MACOS_SURFACE (surface));
if (child_surface)
*child_surface = surface;
display = gdk_device_get_display (device);
point = [NSEvent mouseLocation];
_gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (display),
point.x, point.y,
&x_tmp, &y_tmp);
if (surface)
_gdk_macos_surface_get_root_coords (GDK_MACOS_SURFACE (surface), &sx, &sy);
if (win_x)
*win_x = x_tmp - sx;
if (win_y)
*win_y = y_tmp - sy;
if (mask)
*mask = _gdk_macos_display_get_current_keyboard_modifiers (GDK_MACOS_DISPLAY (display)) |
_gdk_macos_display_get_current_mouse_modifiers (GDK_MACOS_DISPLAY (display));
}
static void
gdk_macos_device_class_init (GdkMacosDeviceClass *klass)
{
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
device_class->get_state = gdk_macos_device_get_state;
device_class->grab = gdk_macos_device_grab;
device_class->query_state = gdk_macos_device_query_state;
device_class->set_surface_cursor = gdk_macos_device_set_surface_cursor;
device_class->surface_at_position = gdk_macos_device_surface_at_position;
device_class->ungrab = gdk_macos_device_ungrab;
}
static void
gdk_macos_device_init (GdkMacosDevice *self)
{
_gdk_device_add_axis (GDK_DEVICE (self), GDK_AXIS_X, 0, 0, 1);
_gdk_device_add_axis (GDK_DEVICE (self), GDK_AXIS_Y, 0, 0, 1);
}

View File

@ -0,0 +1,43 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_DEVICE_H__
#define __GDK_MACOS_DEVICE_H__
#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/macos/gdkmacos.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
typedef struct _GdkMacosDevice GdkMacosDevice;
typedef struct _GdkMacosDeviceClass GdkMacosDeviceClass;
#define GDK_TYPE_MACOS_DEVICE (gdk_macos_device_get_type())
#define GDK_MACOS_DEVICE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DEVICE, GdkMacosDevice))
#define GDK_IS_MACOS_DEVICE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DEVICE))
GDK_AVAILABLE_IN_ALL
GType gdk_macos_device_get_type (void);
G_END_DECLS
#endif /* __GDK_MACOS_DEVICE_H__ */

View File

@ -0,0 +1,154 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_DISPLAY_PRIVATE_H__
#define __GDK_MACOS_DISPLAY_PRIVATE_H__
#include <AppKit/AppKit.h>
#include "gdkdisplayprivate.h"
#include "gdkmacosdisplay.h"
#include "gdkmacoskeymap.h"
#include "gdkmacossurface.h"
G_BEGIN_DECLS
struct _GdkMacosDisplay
{
GdkDisplay parent_instance;
char *name;
GdkMacosKeymap *keymap;
/* An list of GdkMacosMonitor. The first instance is always the primary
* monitor. This contains the 0,0 coordinate in quartz coordinates, but may
* not be 0,0 in GDK coordinates.
*/
GListStore *monitors;
/* A queue of surfaces that have been made "main" so that we can update the
* main status to the next surface when a window has lost main status (such
* as when destroyed). This uses the GdkMacosSurface main link.
*/
GQueue main_surfaces;
/* A queue of surfaces sorted by their front-to-back ordering on the screen.
* This is updated occasionally when we know that the data we have cached
* has been invalidated. This uses the GdkMacosSurface.sorted link.
*/
GQueue sorted_surfaces;
/* Our CVDisplayLink based GSource which we use to freeze/thaw the
* GdkFrameClock for the surface.
*/
GSource *frame_source;
/* A queue of surfaces which we know are awaiting frames to be drawn. This
* uses the GdkMacosSurface.frame link.
*/
GQueue awaiting_frames;
/* The surface that is receiving keyboard events */
GdkMacosSurface *keyboard_surface;
/* Used to translate from quartz coordinate space to GDK */
int width;
int height;
int min_x;
int min_y;
int max_x;
int max_y;
};
struct _GdkMacosDisplayClass
{
GdkDisplayClass parent_class;
};
GdkDisplay *_gdk_macos_display_open (const gchar *display_name);
int _gdk_macos_display_get_fd (GdkMacosDisplay *self);
void _gdk_macos_display_queue_events (GdkMacosDisplay *self);
void _gdk_macos_display_to_display_coords (GdkMacosDisplay *self,
int x,
int y,
int *out_x,
int *out_y);
void _gdk_macos_display_from_display_coords (GdkMacosDisplay *self,
int x,
int y,
int *out_x,
int *out_y);
NSScreen *_gdk_macos_display_get_screen_at_display_coords (GdkMacosDisplay *self,
int x,
int y);
GdkMonitor *_gdk_macos_display_get_monitor_at_coords (GdkMacosDisplay *self,
int x,
int y);
GdkMonitor *_gdk_macos_display_get_monitor_at_display_coords (GdkMacosDisplay *self,
int x,
int y);
GdkEvent *_gdk_macos_display_translate (GdkMacosDisplay *self,
NSEvent *event);
void _gdk_macos_display_break_all_grabs (GdkMacosDisplay *self,
guint32 time);
GdkModifierType _gdk_macos_display_get_current_keyboard_modifiers (GdkMacosDisplay *self);
GdkModifierType _gdk_macos_display_get_current_mouse_modifiers (GdkMacosDisplay *self);
GdkMacosSurface *_gdk_macos_display_get_surface_at_display_coords (GdkMacosDisplay *self,
double x,
double y,
int *surface_x,
int *surface_y);
void _gdk_macos_display_reload_monitors (GdkMacosDisplay *self);
void _gdk_macos_display_surface_removed (GdkMacosDisplay *self,
GdkMacosSurface *surface);
void _gdk_macos_display_add_frame_callback (GdkMacosDisplay *self,
GdkMacosSurface *surface);
void _gdk_macos_display_remove_frame_callback (GdkMacosDisplay *self,
GdkMacosSurface *surface);
void _gdk_macos_display_synthesize_motion (GdkMacosDisplay *self,
GdkMacosSurface *surface);
NSWindow *_gdk_macos_display_find_native_under_pointer (GdkMacosDisplay *self,
int *x,
int *y);
gboolean _gdk_macos_display_get_setting (GdkMacosDisplay *self,
const gchar *setting,
GValue *value);
void _gdk_macos_display_reload_settings (GdkMacosDisplay *self);
void _gdk_macos_display_surface_resigned_main (GdkMacosDisplay *self,
GdkMacosSurface *surface);
void _gdk_macos_display_surface_became_main (GdkMacosDisplay *self,
GdkMacosSurface *surface);
void _gdk_macos_display_surface_resigned_key (GdkMacosDisplay *self,
GdkMacosSurface *surface);
void _gdk_macos_display_surface_became_key (GdkMacosDisplay *self,
GdkMacosSurface *surface);
int _gdk_macos_display_get_nominal_refresh_rate (GdkMacosDisplay *self);
void _gdk_macos_display_clear_sorting (GdkMacosDisplay *self);
const GList *_gdk_macos_display_get_surfaces (GdkMacosDisplay *self);
void _gdk_macos_display_send_button_event (GdkMacosDisplay *self,
NSEvent *nsevent);
void _gdk_macos_display_warp_pointer (GdkMacosDisplay *self,
int x,
int y);
G_END_DECLS
#endif /* __GDK_MACOS_DISPLAY_PRIVATE_H__ */

View File

@ -0,0 +1,194 @@
/*
* Copyright © 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright © 1998-2002 Tor Lillqvist
* Copyright © 2005-2008 Imendio AB
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include <AppKit/AppKit.h>
#include "gdkdisplayprivate.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacosutils-private.h"
typedef struct
{
const char *font_name;
int xft_dpi;
int double_click_time;
int cursor_blink_timeout;
guint enable_animations : 1;
guint shell_shows_desktop : 1;
guint shell_shows_menubar : 1;
guint primary_button_warps_slider : 1;
} GdkMacosSettings;
static GdkMacosSettings current_settings;
static gboolean current_settings_initialized;
static void
_gdk_macos_settings_load (GdkMacosSettings *settings)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *name;
NSInteger ival;
float fval;
char *str;
int pt_size;
g_assert (settings != NULL);
settings->shell_shows_desktop = TRUE;
settings->shell_shows_menubar = TRUE;
settings->enable_animations = TRUE;
settings->xft_dpi = 72 * 1024;
ival = [defaults integerForKey:@"NSTextInsertionPointBlinkPeriod"];
if (ival > 0)
settings->cursor_blink_timeout = ival;
else
settings->cursor_blink_timeout = 1000;
settings->primary_button_warps_slider =
[[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollerPagingBehavior"] == YES;
fval = [defaults floatForKey:@"com.apple.mouse.doubleClickThreshold"];
if (fval == 0.0)
fval = 0.5;
settings->double_click_time = fval * 1000;
name = [[NSFont systemFontOfSize:0] familyName];
pt_size = (gint)[[NSFont userFontOfSize:0] pointSize];
/* Let's try to use the "views" font size (12pt) by default. This is
* used for lists/text/other "content" which is the largest parts of
* apps, using the "regular control" size (13pt) looks a bit out of
* place. We might have to tweak this.
*
* The size has to be hardcoded as there doesn't seem to be a way to
* get the views font size programmatically.
*/
str = g_strdup_printf ("%s %d", [name UTF8String], pt_size);
settings->font_name = g_intern_string (str);
g_free (str);
GDK_END_MACOS_ALLOC_POOL;
}
gboolean
_gdk_macos_display_get_setting (GdkMacosDisplay *self,
const gchar *setting,
GValue *value)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
gboolean ret = FALSE;
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), FALSE);
g_return_val_if_fail (setting != NULL, FALSE);
g_return_val_if_fail (value != NULL, FALSE);
if (!current_settings_initialized)
{
_gdk_macos_settings_load (&current_settings);
current_settings_initialized = TRUE;
}
if (FALSE) {}
else if (strcmp (setting, "gtk-enable-animations") == 0)
{
g_value_set_boolean (value, current_settings.enable_animations);
ret = TRUE;
}
else if (strcmp (setting, "gtk-xft-dpi") == 0)
{
g_value_set_int (value, current_settings.xft_dpi);
ret = TRUE;
}
else if (strcmp (setting, "gtk-cursor-blink-timeout") == 0)
{
g_value_set_int (value, current_settings.cursor_blink_timeout);
ret = TRUE;
}
else if (strcmp (setting, "gtk-double-click-time") == 0)
{
g_value_set_int (value, current_settings.double_click_time);
ret = TRUE;
}
else if (strcmp (setting, "gtk-font-name") == 0)
{
g_value_set_static_string (value, current_settings.font_name);
ret = TRUE;
}
else if (strcmp (setting, "gtk-primary-button-warps-slider") == 0)
{
g_value_set_boolean (value, current_settings.primary_button_warps_slider);
ret = TRUE;
}
else if (strcmp (setting, "gtk-shell-shows-desktop") == 0)
{
g_value_set_boolean (value, current_settings.shell_shows_desktop);
ret = TRUE;
}
else if (strcmp (setting, "gtk-shell-shows-menubar") == 0)
{
g_value_set_boolean (value, current_settings.shell_shows_menubar);
ret = TRUE;
}
GDK_END_MACOS_ALLOC_POOL;
return ret;
}
void
_gdk_macos_display_reload_settings (GdkMacosDisplay *self)
{
GdkMacosSettings old_settings;
g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
old_settings = current_settings;
_gdk_macos_settings_load (&current_settings);
current_settings_initialized = TRUE;
if (old_settings.xft_dpi != current_settings.xft_dpi)
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-xft-dpi");
if (old_settings.double_click_time != current_settings.double_click_time)
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-double-click-time");
if (old_settings.enable_animations != current_settings.enable_animations)
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-enable-animations");
if (old_settings.font_name != current_settings.font_name)
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-font-name");
if (old_settings.primary_button_warps_slider != current_settings.primary_button_warps_slider)
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-primary-button-warps-slider");
if (old_settings.shell_shows_menubar != current_settings.shell_shows_menubar)
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-shell-shows-menubar");
if (old_settings.shell_shows_desktop != current_settings.shell_shows_desktop)
gdk_display_setting_changed (GDK_DISPLAY (self), "gtk-shell-shows-desktop");
}

File diff suppressed because it is too large Load Diff

1071
gdk/macos/gdkmacosdisplay.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,47 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_DISPLAY_H__
#define __GDK_MACOS_DISPLAY_H__
#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/macos/gdkmacos.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
#ifdef GTK_COMPILATION
typedef struct _GdkMacosDisplay GdkMacosDisplay;
#else
typedef GdkDisplay GdkMacosDisplay;
#endif
typedef struct _GdkMacosDisplayClass GdkMacosDisplayClass;
#define GDK_TYPE_MACOS_DISPLAY (gdk_macos_display_get_type())
#define GDK_MACOS_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DISPLAY, GdkMacosDisplay))
#define GDK_IS_MACOS_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DISPLAY))
GDK_AVAILABLE_IN_ALL
GType gdk_macos_display_get_type (void);
G_END_DECLS
#endif /* __GDK_MACOS_DISPLAY_H__ */

View File

@ -0,0 +1,70 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_DRAG_PRIVATE_H__
#define __GDK_MACOS_DRAG_PRIVATE_H__
#include "gdkdragprivate.h"
#include "gdkmacosdragsurface-private.h"
G_BEGIN_DECLS
#define GDK_TYPE_MACOS_DRAG (gdk_macos_drag_get_type ())
#define GDK_MACOS_DRAG(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DRAG, GdkMacosDrag))
#define GDK_MACOS_DRAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_MACOS_DRAG, GdkMacosDragClass))
#define GDK_IS_MACOS_DRAG(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DRAG))
#define GDK_IS_MACOS_DRAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_MACOS_DRAG))
#define GDK_MACOS_DRAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_MACOS_DRAG, GdkMacosDragClass))
typedef struct _GdkMacosDrag GdkMacosDrag;
typedef struct _GdkMacosDragClass GdkMacosDragClass;
struct _GdkMacosDrag
{
GdkDrag parent_instance;
GdkMacosDragSurface *drag_surface;
GdkSeat *drag_seat;
GdkCursor *cursor;
int hot_x;
int hot_y;
int last_x;
int last_y;
int start_x;
int start_y;
guint did_update : 1;
guint cancelled : 1;
};
struct _GdkMacosDragClass
{
GdkDragClass parent_class;
};
GType gdk_macos_drag_get_type (void) G_GNUC_CONST;
gboolean _gdk_macos_drag_begin (GdkMacosDrag *self);
G_END_DECLS
#endif /* __GDK_MACOS_DRAG_PRIVATE_H__ */

617
gdk/macos/gdkmacosdrag.c Normal file
View File

@ -0,0 +1,617 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include "gdkdeviceprivate.h"
#include "gdkintl.h"
#include "gdkmacoscursor-private.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacosdrag-private.h"
#include "gdkmacosdragsurface-private.h"
#define BIG_STEP 20
#define SMALL_STEP 1
#define ANIM_TIME 500000 /* .5 seconds */
typedef struct
{
GdkMacosDrag *drag;
GdkFrameClock *frame_clock;
gint64 start_time;
} GdkMacosZoomback;
G_DEFINE_TYPE (GdkMacosDrag, gdk_macos_drag, GDK_TYPE_DRAG)
enum {
PROP_0,
PROP_DRAG_SURFACE,
N_PROPS
};
static GParamSpec *properties [N_PROPS];
static double
ease_out_cubic (double t)
{
double p = t - 1;
return p * p * p + 1;
}
static void
gdk_macos_zoomback_destroy (GdkMacosZoomback *zb)
{
gdk_surface_hide (GDK_SURFACE (zb->drag->drag_surface));
g_clear_object (&zb->drag);
g_slice_free (GdkMacosZoomback, zb);
}
static gboolean
gdk_macos_zoomback_timeout (gpointer data)
{
GdkMacosZoomback *zb = data;
GdkFrameClock *frame_clock;
GdkMacosDrag *drag;
gint64 current_time;
double f;
double t;
g_assert (zb != NULL);
g_assert (GDK_IS_MACOS_DRAG (zb->drag));
drag = zb->drag;
frame_clock = zb->frame_clock;
if (!frame_clock)
return G_SOURCE_REMOVE;
current_time = gdk_frame_clock_get_frame_time (frame_clock);
f = (current_time - zb->start_time) / (double) ANIM_TIME;
if (f >= 1.0)
return G_SOURCE_REMOVE;
t = ease_out_cubic (f);
_gdk_macos_surface_move (GDK_MACOS_SURFACE (drag->drag_surface),
(drag->last_x - drag->hot_x) +
(drag->start_x - drag->last_x) * t,
(drag->last_y - drag->hot_y) +
(drag->start_y - drag->last_y) * t);
_gdk_macos_surface_set_opacity (GDK_MACOS_SURFACE (drag->drag_surface), 1.0 - f);
/* Make sure we're topmost */
_gdk_macos_surface_show (GDK_MACOS_SURFACE (drag->drag_surface));
return G_SOURCE_CONTINUE;
}
static GdkSurface *
gdk_macos_drag_get_drag_surface (GdkDrag *drag)
{
return GDK_SURFACE (GDK_MACOS_DRAG (drag)->drag_surface);
}
static void
gdk_macos_drag_set_hotspot (GdkDrag *drag,
int hot_x,
int hot_y)
{
GdkMacosDrag *self = (GdkMacosDrag *)drag;
int change_x;
int change_y;
g_assert (GDK_IS_MACOS_DRAG (self));
change_x = hot_x - self->hot_x;
change_y = hot_y - self->hot_y;
self->hot_x = hot_x;
self->hot_y = hot_y;
if (change_x || change_y)
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self->drag_surface),
GDK_SURFACE (self->drag_surface)->x + change_x,
GDK_SURFACE (self->drag_surface)->y + change_y);
}
static void
gdk_macos_drag_drop_done (GdkDrag *drag,
gboolean success)
{
GdkMacosDrag *self = (GdkMacosDrag *)drag;
GdkMacosZoomback *zb;
guint id;
g_assert (GDK_IS_MACOS_DRAG (self));
if (success)
{
gdk_surface_hide (GDK_SURFACE (self->drag_surface));
g_object_unref (drag);
return;
}
/* Apple HIG suggests doing a "zoomback" animation of the surface back
* towards the original position.
*/
zb = g_slice_new0 (GdkMacosZoomback);
zb->drag = g_object_ref (self);
zb->frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self->drag_surface));
zb->start_time = gdk_frame_clock_get_frame_time (zb->frame_clock);
id = g_timeout_add_full (G_PRIORITY_DEFAULT, 17,
gdk_macos_zoomback_timeout,
zb,
(GDestroyNotify) gdk_macos_zoomback_destroy);
g_source_set_name_by_id (id, "[gtk] gdk_macos_zoomback_timeout");
g_object_unref (drag);
}
static void
gdk_macos_drag_set_cursor (GdkDrag *drag,
GdkCursor *cursor)
{
GdkMacosDrag *self = (GdkMacosDrag *)drag;
NSCursor *nscursor;
g_assert (GDK_IS_MACOS_DRAG (self));
g_assert (!cursor || GDK_IS_CURSOR (cursor));
g_set_object (&self->cursor, cursor);
nscursor = _gdk_macos_cursor_get_ns_cursor (cursor);
if (nscursor != NULL)
[nscursor set];
}
static gboolean
drag_grab (GdkMacosDrag *self)
{
GdkSeat *seat;
g_assert (GDK_IS_MACOS_DRAG (self));
seat = gdk_device_get_seat (gdk_drag_get_device (GDK_DRAG (self)));
if (gdk_seat_grab (seat,
GDK_SURFACE (self->drag_surface),
GDK_SEAT_CAPABILITY_ALL_POINTING,
FALSE,
self->cursor,
NULL,
NULL,
NULL) != GDK_GRAB_SUCCESS)
return FALSE;
g_set_object (&self->drag_seat, seat);
return TRUE;
}
static void
drag_ungrab (GdkMacosDrag *self)
{
GdkDisplay *display;
g_assert (GDK_IS_MACOS_DRAG (self));
display = gdk_drag_get_display (GDK_DRAG (self));
_gdk_macos_display_break_all_grabs (GDK_MACOS_DISPLAY (display), GDK_CURRENT_TIME);
}
static void
gdk_macos_drag_cancel (GdkDrag *drag,
GdkDragCancelReason reason)
{
GdkMacosDrag *self = (GdkMacosDrag *)drag;
g_assert (GDK_IS_MACOS_DRAG (self));
if (self->cancelled)
return;
self->cancelled = TRUE;
drag_ungrab (self);
gdk_drag_drop_done (drag, FALSE);
}
static void
gdk_macos_drag_drop_performed (GdkDrag *drag,
guint32 time)
{
GdkMacosDrag *self = (GdkMacosDrag *)drag;
g_assert (GDK_IS_MACOS_DRAG (self));
drag_ungrab (self);
g_signal_emit_by_name (drag, "dnd-finished");
gdk_drag_drop_done (drag, TRUE);
}
static void
gdk_drag_get_current_actions (GdkModifierType state,
gint button,
GdkDragAction actions,
GdkDragAction *suggested_action,
GdkDragAction *possible_actions)
{
*suggested_action = 0;
*possible_actions = 0;
if ((button == GDK_BUTTON_MIDDLE || button == GDK_BUTTON_SECONDARY) && (actions & GDK_ACTION_ASK))
{
*suggested_action = GDK_ACTION_ASK;
*possible_actions = actions;
}
else if (state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK))
{
if ((state & GDK_SHIFT_MASK) && (state & GDK_CONTROL_MASK))
{
if (actions & GDK_ACTION_LINK)
{
*suggested_action = GDK_ACTION_LINK;
*possible_actions = GDK_ACTION_LINK;
}
}
else if (state & GDK_CONTROL_MASK)
{
if (actions & GDK_ACTION_COPY)
{
*suggested_action = GDK_ACTION_COPY;
*possible_actions = GDK_ACTION_COPY;
}
}
else
{
if (actions & GDK_ACTION_MOVE)
{
*suggested_action = GDK_ACTION_MOVE;
*possible_actions = GDK_ACTION_MOVE;
}
}
}
else
{
*possible_actions = actions;
if ((state & (GDK_ALT_MASK)) && (actions & GDK_ACTION_ASK))
*suggested_action = GDK_ACTION_ASK;
else if (actions & GDK_ACTION_COPY)
*suggested_action = GDK_ACTION_COPY;
else if (actions & GDK_ACTION_MOVE)
*suggested_action = GDK_ACTION_MOVE;
else if (actions & GDK_ACTION_LINK)
*suggested_action = GDK_ACTION_LINK;
}
}
static void
gdk_drag_update (GdkDrag *drag,
gdouble x_root,
gdouble y_root,
GdkModifierType mods,
guint32 evtime)
{
GdkMacosDrag *self = (GdkMacosDrag *)drag;
GdkDragAction suggested_action;
GdkDragAction possible_actions;
g_assert (GDK_IS_MACOS_DRAG (self));
self->last_x = x_root;
self->last_y = y_root;
gdk_drag_get_current_actions (mods,
GDK_BUTTON_PRIMARY,
gdk_drag_get_actions (drag),
&suggested_action,
&possible_actions);
_gdk_macos_drag_surface_drag_motion (self->drag_surface,
x_root - self->hot_x,
y_root - self->hot_y,
suggested_action,
possible_actions,
evtime);
if (!self->did_update)
{
self->start_x = self->last_x;
self->start_y = self->last_y;
self->did_update = TRUE;
}
}
static gboolean
gdk_dnd_handle_motion_event (GdkDrag *drag,
GdkEvent *event)
{
double x, y;
int x_root, y_root;
g_assert (GDK_IS_MACOS_DRAG (drag));
g_assert (event != NULL);
/* Ignore motion while doing zoomback */
if (GDK_MACOS_DRAG (drag)->cancelled)
return FALSE;
gdk_event_get_position (event, &x, &y);
x_root = event->surface->x + x;
y_root = event->surface->y + y;
gdk_drag_update (drag, x_root, y_root,
gdk_event_get_modifier_state (event),
gdk_event_get_time (event));
return TRUE;
}
static gboolean
gdk_dnd_handle_grab_broken_event (GdkDrag *drag,
GdkEvent *event)
{
GdkMacosDrag *self = GDK_MACOS_DRAG (drag);
gboolean is_implicit = gdk_grab_broken_event_get_implicit (event);
GdkSurface *grab_surface = gdk_grab_broken_event_get_grab_surface (event);
/* Don't cancel if we break the implicit grab from the initial button_press. */
if (is_implicit || grab_surface == (GdkSurface *)self->drag_surface)
return FALSE;
if (gdk_event_get_device (event) != gdk_drag_get_device (drag))
return FALSE;
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_ERROR);
return TRUE;
}
static gboolean
gdk_dnd_handle_button_event (GdkDrag *drag,
GdkEvent *event)
{
GdkMacosDrag *self = GDK_MACOS_DRAG (drag);
g_assert (GDK_IS_MACOS_DRAG (self));
g_assert (event != NULL);
#if 0
/* FIXME: Check the button matches */
if (event->button != self->button)
return FALSE;
#endif
if (gdk_drag_get_selected_action (drag) != 0)
g_signal_emit_by_name (drag, "drop-performed");
else
gdk_drag_cancel (drag, GDK_DRAG_CANCEL_NO_TARGET);
return TRUE;
}
static gboolean
gdk_dnd_handle_key_event (GdkDrag *drag,
GdkEvent *event)
{
GdkMacosDrag *self = GDK_MACOS_DRAG (drag);
GdkModifierType state;
GdkDevice *pointer;
gint dx, dy;
dx = dy = 0;
state = gdk_event_get_modifier_state (event);
pointer = gdk_device_get_associated_device (gdk_event_get_device (event));
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)
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_device_query_state (pointer, NULL, NULL, NULL, NULL, &state);
if (dx != 0 || dy != 0)
{
GdkDisplay *display = gdk_event_get_display ((GdkEvent *)event);
self->last_x += dx;
self->last_y += dy;
_gdk_macos_display_warp_pointer (GDK_MACOS_DISPLAY (display),
self->last_x,
self->last_y);
}
gdk_drag_update (drag,
self->last_x, self->last_y,
state,
gdk_event_get_time (event));
return TRUE;
}
static gboolean
gdk_macos_drag_handle_event (GdkDrag *drag,
GdkEvent *event)
{
g_assert (GDK_IS_MACOS_DRAG (drag));
g_assert (event != NULL);
switch ((guint) event->event_type)
{
case GDK_MOTION_NOTIFY:
return gdk_dnd_handle_motion_event (drag, event);
case GDK_BUTTON_RELEASE:
return gdk_dnd_handle_button_event (drag, event);
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
return gdk_dnd_handle_key_event (drag, event);
case GDK_GRAB_BROKEN:
return gdk_dnd_handle_grab_broken_event (drag, event);
default:
return FALSE;
}
}
static void
gdk_macos_drag_finalize (GObject *object)
{
GdkMacosDrag *self = (GdkMacosDrag *)object;
GdkMacosDragSurface *drag_surface = g_steal_pointer (&self->drag_surface);
g_clear_object (&self->cursor);
g_clear_object (&self->drag_seat);
G_OBJECT_CLASS (gdk_macos_drag_parent_class)->finalize (object);
if (drag_surface)
gdk_surface_destroy (GDK_SURFACE (drag_surface));
}
static void
gdk_macos_drag_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkMacosDrag *self = GDK_MACOS_DRAG (object);
switch (prop_id)
{
case PROP_DRAG_SURFACE:
g_value_set_object (value, self->drag_surface);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gdk_macos_drag_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GdkMacosDrag *self = GDK_MACOS_DRAG (object);
switch (prop_id)
{
case PROP_DRAG_SURFACE:
self->drag_surface = g_value_dup_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gdk_macos_drag_class_init (GdkMacosDragClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkDragClass *drag_class = GDK_DRAG_CLASS (klass);
object_class->finalize = gdk_macos_drag_finalize;
object_class->get_property = gdk_macos_drag_get_property;
object_class->set_property = gdk_macos_drag_set_property;
drag_class->get_drag_surface = gdk_macos_drag_get_drag_surface;
drag_class->set_hotspot = gdk_macos_drag_set_hotspot;
drag_class->drop_done = gdk_macos_drag_drop_done;
drag_class->set_cursor = gdk_macos_drag_set_cursor;
drag_class->cancel = gdk_macos_drag_cancel;
drag_class->drop_performed = gdk_macos_drag_drop_performed;
drag_class->handle_event = gdk_macos_drag_handle_event;
properties [PROP_DRAG_SURFACE] =
g_param_spec_object ("drag-surface",
P_("Drag Surface"),
P_("Drag Surface"),
GDK_TYPE_MACOS_DRAG_SURFACE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
gdk_macos_drag_init (GdkMacosDrag *self)
{
}
gboolean
_gdk_macos_drag_begin (GdkMacosDrag *self)
{
g_return_val_if_fail (GDK_IS_MACOS_DRAG (self), FALSE);
_gdk_macos_surface_show (GDK_MACOS_SURFACE (self->drag_surface));
return drag_grab (self);
}

View File

@ -0,0 +1,50 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_DRAG_SURFACE_PRIVATE_H__
#define __GDK_MACOS_DRAG_SURFACE_PRIVATE_H__
#include "gdkmacossurface-private.h"
G_BEGIN_DECLS
typedef struct _GdkMacosDragSurface GdkMacosDragSurface;
typedef struct _GdkMacosDragSurfaceClass GdkMacosDragSurfaceClass;
#define GDK_TYPE_MACOS_DRAG_SURFACE (_gdk_macos_drag_surface_get_type())
#define GDK_MACOS_DRAG_SURFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DRAG_SURFACE, GdkMacosDragSurface))
#define GDK_IS_MACOS_DRAG_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DRAG_SURFACE))
GType _gdk_macos_drag_surface_get_type (void);
GdkMacosSurface *_gdk_macos_drag_surface_new (GdkMacosDisplay *display,
GdkFrameClock *frame_clock,
int x,
int y,
int width,
int height);
void _gdk_macos_drag_surface_drag_motion (GdkMacosDragSurface *self,
int x_root,
int y_root,
GdkDragAction suggested_action,
GdkDragAction possible_actions,
guint32 evtime);
G_END_DECLS
#endif /* __GDK_MACOS_DRAG_SURFACE_PRIVATE_H__ */

View File

@ -0,0 +1,138 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include "gdkdragsurfaceprivate.h"
#include "gdkmacosdragsurface-private.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacosutils-private.h"
struct _GdkMacosDragSurface
{
GdkMacosSurface parent_instance;
};
struct _GdkMacosDragSurfaceClass
{
GdkMacosSurfaceClass parent_instance;
};
static gboolean
_gdk_macos_drag_surface_present (GdkDragSurface *surface,
int width,
int height)
{
g_assert (GDK_IS_MACOS_SURFACE (surface));
_gdk_macos_surface_move_resize (GDK_MACOS_SURFACE (surface),
-1, -1,
width, height);
if (!GDK_SURFACE_IS_MAPPED (GDK_SURFACE (surface)))
_gdk_macos_surface_show (GDK_MACOS_SURFACE (surface));
return GDK_SURFACE_IS_MAPPED (GDK_SURFACE (surface));
}
static void
drag_surface_iface_init (GdkDragSurfaceInterface *iface)
{
iface->present = _gdk_macos_drag_surface_present;
}
G_DEFINE_TYPE_WITH_CODE (GdkMacosDragSurface, _gdk_macos_drag_surface, GDK_TYPE_MACOS_SURFACE,
G_IMPLEMENT_INTERFACE (GDK_TYPE_DRAG_SURFACE, drag_surface_iface_init))
static void
_gdk_macos_drag_surface_class_init (GdkMacosDragSurfaceClass *klass)
{
}
static void
_gdk_macos_drag_surface_init (GdkMacosDragSurface *self)
{
}
GdkMacosSurface *
_gdk_macos_drag_surface_new (GdkMacosDisplay *display,
GdkFrameClock *frame_clock,
int x,
int y,
int width,
int height)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkMacosWindow *window;
GdkMacosSurface *self;
NSScreen *screen;
NSUInteger style_mask;
NSRect content_rect;
NSRect screen_rect;
int nx;
int ny;
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
g_return_val_if_fail (!frame_clock || GDK_IS_FRAME_CLOCK (frame_clock), NULL);
style_mask = NSWindowStyleMaskBorderless;
_gdk_macos_display_to_display_coords (display, x, y, &nx, &ny);
screen = _gdk_macos_display_get_screen_at_display_coords (display, nx, ny);
screen_rect = [screen frame];
nx -= screen_rect.origin.x;
ny -= screen_rect.origin.y;
content_rect = NSMakeRect (nx, ny - height, width, height);
window = [[GdkMacosWindow alloc] initWithContentRect:content_rect
styleMask:style_mask
backing:NSBackingStoreBuffered
defer:NO
screen:screen];
[window setOpaque:NO];
[window setBackgroundColor:[NSColor clearColor]];
[window setDecorated:NO];
self = g_object_new (GDK_TYPE_MACOS_DRAG_SURFACE,
"display", display,
"frame-clock", frame_clock,
"native", window,
NULL);
GDK_END_MACOS_ALLOC_POOL;
return g_steal_pointer (&self);
}
void
_gdk_macos_drag_surface_drag_motion (GdkMacosDragSurface *self,
int x_root,
int y_root,
GdkDragAction suggested_action,
GdkDragAction possible_actions,
guint32 evtime)
{
g_return_if_fail (GDK_IS_MACOS_DRAG_SURFACE (self));
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self), x_root, y_root);
}

View File

@ -0,0 +1,40 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_EVENT_SOURCE_PRIVATE_H__
#define __GDK_MACOS_EVENT_SOURCE_PRIVATE_H__
#include <AppKit/AppKit.h>
#include "gdkmacosdisplay.h"
G_BEGIN_DECLS
typedef enum
{
GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP,
} GdkMacosEventSubType;
GSource *_gdk_macos_event_source_new (GdkMacosDisplay *display);
NSEvent *_gdk_macos_event_source_get_pending (void);
gboolean _gdk_macos_event_source_check_pending (void);
G_END_DECLS
#endif /* __GDK_MACOS_EVENT_SOURCE_PRIVATE_H__ */

View File

@ -1,3 +1,23 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 2005-2007 Imendio AB
*
* 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include <glib.h>
@ -6,10 +26,13 @@
#include <sys/uio.h>
#include <unistd.h>
#include "gdkprivate-quartz.h"
#include <gdk/gdkdisplayprivate.h>
#include "gdkdisplayprivate.h"
#include "gdkinternals.h"
/*
#include "gdkmacoseventsource-private.h"
#include "gdkmacosdisplay-private.h"
/*
* This file implementations integration between the GLib main loop and
* the native system of the Core Foundation run loop and Cocoa event
* handling. There are basically two different cases that we need to
@ -55,16 +78,16 @@ static int current_loop_level = 0;
/* Run loop level at which we acquired ownership of the GLib main
* loop. See note in run_loop_entry(). -1 means that we dont have
* ownership
*/
*/
static int acquired_loop_level = -1;
/* Between run_loop_before_waiting() and run_loop_after_waiting();
* whether we need to call select_thread_collect_poll()
* whether we we need to call select_thread_collect_poll()
*/
static gboolean run_loop_polling_async = FALSE;
/* Between run_loop_before_waiting() and run_loop_after_waiting();
* max_priority to pass to g_main_loop_check()
* max_prioritiy to pass to g_main_loop_check()
*/
static gint run_loop_max_priority;
@ -95,7 +118,7 @@ static GPollFD event_poll_fd;
/* Current NSEvents that we've gotten from Cocoa but haven't yet converted
* to GdkEvents. We wait until our dispatch() function to do the conversion
* since the conversion can conceivably cause signals to be emitted
* since the conversion can conceivably cause signals to be emmitted
* or other things that shouldnt happen inside a poll function.
*/
static GQueue *current_events;
@ -132,7 +155,7 @@ static gint getting_events = 0;
************************************************************/
/* The states in our state machine, see comments in select_thread_func()
* for descriptions of each state
* for descriptiions of each state
*/
typedef enum {
BEFORE_START,
@ -220,93 +243,93 @@ static void *
select_thread_func (void *arg)
{
char c;
SELECT_THREAD_LOCK ();
while (TRUE)
{
switch (select_thread_state)
{
case BEFORE_START:
/* The select thread has not been started yet
*/
g_assert_not_reached ();
case WAITING:
/* Waiting for a set of file descriptors to be submitted by the main thread
*
* => POLLING_QUEUED: main thread submits a set of file descriptors
*/
SELECT_THREAD_WAIT ();
break;
case POLLING_QUEUED:
/* Waiting for a set of file descriptors to be submitted by the main thread
*
* => POLLING_DESCRIPTORS: select thread picks up the file descriptors to begin polling
*/
g_free (current_pollfds);
current_pollfds = next_pollfds;
current_n_pollfds = next_n_pollfds;
{
case BEFORE_START:
/* The select thread has not been started yet
*/
g_assert_not_reached ();
next_pollfds = NULL;
next_n_pollfds = 0;
case WAITING:
/* Waiting for a set of file descriptors to be submitted by the main thread
*
* => POLLING_QUEUED: main thread thread submits a set of file descriptors
*/
SELECT_THREAD_WAIT ();
break;
select_thread_set_state (POLLING_DESCRIPTORS);
break;
case POLLING_RESTART:
/* Select thread is currently polling a set of file descriptors, main thread has
* began a new iteration with the same set of file descriptors. We don't want to
* wake the select thread up and wait for it to restart immediately, but to avoid
* a race (described below in select_thread_start_polling()) we need to recheck after
* polling completes.
*
* => POLLING_DESCRIPTORS: select completes, main thread rechecks by polling again
* => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
*/
select_thread_set_state (POLLING_DESCRIPTORS);
break;
case POLLING_QUEUED:
/* Waiting for a set of file descriptors to be submitted by the main thread
*
* => POLLING_DESCRIPTORS: select thread picks up the file descriptors to begin polling
*/
g_free (current_pollfds);
case POLLING_DESCRIPTORS:
/* In the process of polling the file descriptors
*
* => WAITING: polling completes when a file descriptor becomes active
* => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
* => POLLING_RESTART: main thread begins a new iteration with the same set file descriptors
*/
SELECT_THREAD_UNLOCK ();
old_poll_func (current_pollfds, current_n_pollfds, -1);
SELECT_THREAD_LOCK ();
current_pollfds = next_pollfds;
current_n_pollfds = next_n_pollfds;
read (select_thread_wakeup_pipe[0], &c, 1);
next_pollfds = NULL;
next_n_pollfds = 0;
if (select_thread_state == POLLING_DESCRIPTORS)
{
signal_main_thread ();
select_thread_set_state (WAITING);
}
break;
}
select_thread_set_state (POLLING_DESCRIPTORS);
break;
case POLLING_RESTART:
/* Select thread is currently polling a set of file descriptors, main thread has
* began a new iteration with the same set of file descriptors. We don't want to
* wake the select thread up and wait for it to restart immediately, but to avoid
* a race (described below in select_thread_start_polling()) we need to recheck after
* polling completes.
*
* => POLLING_DESCRIPTORS: select completes, main thread rechecks by polling again
* => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
*/
select_thread_set_state (POLLING_DESCRIPTORS);
break;
case POLLING_DESCRIPTORS:
/* In the process of polling the file descriptors
*
* => WAITING: polling completes when a file descriptor becomes active
* => POLLING_QUEUED: main thread submits a new set of file descriptors to be polled
* => POLLING_RESTART: main thread begins a new iteration with the same set file descriptors
*/
SELECT_THREAD_UNLOCK ();
old_poll_func (current_pollfds, current_n_pollfds, -1);
SELECT_THREAD_LOCK ();
read (select_thread_wakeup_pipe[0], &c, 1);
if (select_thread_state == POLLING_DESCRIPTORS)
{
signal_main_thread ();
select_thread_set_state (WAITING);
}
break;
}
}
}
static void
static void
got_fd_activity (void *info)
{
NSEvent *event;
/* Post a message so we'll break out of the message loop */
event = [NSEvent otherEventWithType: NSApplicationDefined
location: NSZeroPoint
modifierFlags: 0
timestamp: 0
windowNumber: 0
context: nil
subtype: GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP
data1: 0
data2: 0];
event = [NSEvent otherEventWithType: NSEventTypeApplicationDefined
location: NSZeroPoint
modifierFlags: 0
timestamp: 0
windowNumber: 0
context: nil
subtype: GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP
data1: 0
data2: 0];
[NSApp postEvent:event atStart:YES];
}
@ -315,21 +338,21 @@ static void
select_thread_start (void)
{
g_return_if_fail (select_thread_state == BEFORE_START);
pipe (select_thread_wakeup_pipe);
fcntl (select_thread_wakeup_pipe[0], F_SETFL, O_NONBLOCK);
CFRunLoopSourceContext source_context = {0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, got_fd_activity };
select_main_thread_source = CFRunLoopSourceCreate (NULL, 0, &source_context);
CFRunLoopAddSource (main_thread_run_loop, select_main_thread_source, kCFRunLoopCommonModes);
select_thread_state = WAITING;
while (TRUE)
{
if (pthread_create (&select_thread, NULL, select_thread_func, NULL) == 0)
break;
break;
g_warning ("Failed to create select thread, sleeping and trying again");
sleep (1);
@ -339,7 +362,7 @@ select_thread_start (void)
#ifdef G_ENABLE_DEBUG
static void
dump_poll_result (GPollFD *ufds,
guint nfds)
guint nfds)
{
GString *s;
gint i;
@ -348,44 +371,44 @@ dump_poll_result (GPollFD *ufds,
for (i = 0; i < nfds; i++)
{
if (ufds[i].fd >= 0 && ufds[i].revents)
{
{
g_string_append_printf (s, " %d:", ufds[i].fd);
if (ufds[i].revents & G_IO_IN)
if (ufds[i].revents & G_IO_IN)
g_string_append (s, " in");
if (ufds[i].revents & G_IO_OUT)
g_string_append (s, " out");
if (ufds[i].revents & G_IO_PRI)
g_string_append (s, " pri");
g_string_append (s, "\n");
}
if (ufds[i].revents & G_IO_OUT)
g_string_append (s, " out");
if (ufds[i].revents & G_IO_PRI)
g_string_append (s, " pri");
g_string_append (s, "\n");
}
}
g_message ("%s", s->str);
g_string_free (s, TRUE);
}
#endif
gboolean
static gboolean
pollfds_equal (GPollFD *old_pollfds,
guint old_n_pollfds,
GPollFD *new_pollfds,
guint new_n_pollfds)
guint old_n_pollfds,
GPollFD *new_pollfds,
guint new_n_pollfds)
{
gint i;
if (old_n_pollfds != new_n_pollfds)
return FALSE;
for (i = 0; i < old_n_pollfds; i++)
{
if (old_pollfds[i].fd != new_pollfds[i].fd ||
old_pollfds[i].events != new_pollfds[i].events)
return FALSE;
old_pollfds[i].events != new_pollfds[i].events)
return FALSE;
}
return TRUE;
}
/* Begins a polling operation with the specified GPollFD array; the
/* Begins a polling operation with the specified GPollFD array; the
* timeout is used only to tell if the polling operation is blocking
* or non-blocking.
*
@ -396,7 +419,8 @@ pollfds_equal (GPollFD *old_pollfds,
*/
static gint
select_thread_start_poll (GPollFD *ufds,
guint nfds, gint timeout)
guint nfds,
gint timeout)
{
gint n_ready;
gboolean have_new_pollfds = FALSE;
@ -406,10 +430,10 @@ select_thread_start_poll (GPollFD *ufds,
for (i = 0; i < nfds; i++)
if (ufds[i].fd == -1)
{
poll_fd_index = i;
break;
poll_fd_index = i;
break;
}
if (nfds == 0 ||
(nfds == 1 && poll_fd_index >= 0))
{
@ -431,35 +455,35 @@ select_thread_start_poll (GPollFD *ufds,
{
#ifdef G_ENABLE_DEBUG
if ((_gdk_debug_flags & GDK_DEBUG_EVENTLOOP) && n_ready > 0)
{
g_message ("EventLoop: Found ready file descriptors before waiting");
dump_poll_result (ufds, nfds);
}
{
g_message ("EventLoop: Found ready file descriptors before waiting");
dump_poll_result (ufds, nfds);
}
#endif
return n_ready;
}
SELECT_THREAD_LOCK ();
if (select_thread_state == BEFORE_START)
{
select_thread_start ();
}
if (select_thread_state == POLLING_QUEUED)
{
/* If the select thread hasn't picked up the set of file descriptors yet
* then we can simply replace an old stale set with a new set.
*/
if (!pollfds_equal (ufds, nfds, next_pollfds, next_n_pollfds - 1))
{
g_free (next_pollfds);
next_pollfds = NULL;
next_n_pollfds = 0;
have_new_pollfds = TRUE;
}
{
g_free (next_pollfds);
next_pollfds = NULL;
next_n_pollfds = 0;
have_new_pollfds = TRUE;
}
}
else if (select_thread_state == POLLING_RESTART || select_thread_state == POLLING_DESCRIPTORS)
{
@ -481,7 +505,7 @@ select_thread_start_poll (GPollFD *ufds,
* Marks polling as complete
* Wakes main thread
* Receives old stale file descriptor state
*
*
* To avoid this, when the new set of poll descriptors is the same as the current
* one, we transition to the POLLING_RESTART stage at the point marked (*). When
* the select thread wakes up from the poll because a file descriptor is active, if
@ -498,13 +522,13 @@ select_thread_start_poll (GPollFD *ufds,
* from a file descriptor that hangs.
*/
if (!pollfds_equal (ufds, nfds, current_pollfds, current_n_pollfds - 1))
have_new_pollfds = TRUE;
have_new_pollfds = TRUE;
else
{
if (!((nfds == 1 && poll_fd_index < 0 && g_thread_supported ()) ||
(nfds == 2 && poll_fd_index >= 0 && g_thread_supported ())))
select_thread_set_state (POLLING_RESTART);
}
{
if (!((nfds == 1 && poll_fd_index < 0 && g_thread_supported ()) ||
(nfds == 2 && poll_fd_index >= 0 && g_thread_supported ())))
select_thread_set_state (POLLING_RESTART);
}
}
else
have_new_pollfds = TRUE;
@ -512,28 +536,28 @@ select_thread_start_poll (GPollFD *ufds,
if (have_new_pollfds)
{
GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Submitting a new set of file descriptor to the select thread"));
g_assert (next_pollfds == NULL);
next_n_pollfds = nfds + 1;
next_pollfds = g_new (GPollFD, nfds + 1);
memcpy (next_pollfds, ufds, nfds * sizeof (GPollFD));
next_pollfds[nfds].fd = select_thread_wakeup_pipe[0];
next_pollfds[nfds].events = G_IO_IN;
if (select_thread_state != POLLING_QUEUED && select_thread_state != WAITING)
{
if (select_thread_wakeup_pipe[1])
{
char c = 'A';
write (select_thread_wakeup_pipe[1], &c, 1);
}
}
{
if (select_thread_wakeup_pipe[1])
{
char c = 'A';
write (select_thread_wakeup_pipe[1], &c, 1);
}
}
select_thread_set_state (POLLING_QUEUED);
}
SELECT_THREAD_UNLOCK ();
return -1;
@ -553,32 +577,32 @@ select_thread_collect_poll (GPollFD *ufds, guint nfds)
{
gint i;
gint n_ready = 0;
SELECT_THREAD_LOCK ();
if (select_thread_state == WAITING) /* The poll completed */
{
for (i = 0; i < nfds; i++)
{
if (ufds[i].fd == -1)
continue;
g_assert (ufds[i].fd == current_pollfds[i].fd);
g_assert (ufds[i].events == current_pollfds[i].events);
{
if (ufds[i].fd == -1)
continue;
g_assert (ufds[i].fd == current_pollfds[i].fd);
g_assert (ufds[i].events == current_pollfds[i].events);
if (current_pollfds[i].revents)
{
ufds[i].revents = current_pollfds[i].revents;
n_ready++;
}
}
if (current_pollfds[i].revents)
{
ufds[i].revents = current_pollfds[i].revents;
n_ready++;
}
}
#ifdef G_ENABLE_DEBUG
if (_gdk_debug_flags & GDK_DEBUG_EVENTLOOP)
{
g_message ("EventLoop: Found ready file descriptors after waiting");
dump_poll_result (ufds, nfds);
}
{
g_message ("EventLoop: Found ready file descriptors after waiting");
dump_poll_result (ufds, nfds);
}
#endif
}
@ -591,14 +615,20 @@ select_thread_collect_poll (GPollFD *ufds, guint nfds)
********* Main Loop Source *********
************************************************************/
typedef struct _GdkMacosEventSource
{
GSource source;
GdkDisplay *display;
} GdkMacosEventSource;
gboolean
_gdk_quartz_event_loop_check_pending (void)
_gdk_macos_event_source_check_pending (void)
{
return current_events && current_events->head;
}
NSEvent*
_gdk_quartz_event_loop_get_pending (void)
NSEvent *
_gdk_macos_event_source_get_pending (void)
{
NSEvent *event = NULL;
@ -608,16 +638,11 @@ _gdk_quartz_event_loop_get_pending (void)
return event;
}
void
_gdk_quartz_event_loop_release_event (NSEvent *event)
{
[event release];
}
static gboolean
gdk_event_prepare (GSource *source,
gint *timeout)
gdk_macos_event_source_prepare (GSource *source,
gint *timeout)
{
GdkMacosEventSource *event_source = (GdkMacosEventSource *)source;
gboolean retval;
/* The prepare stage is the stage before the main loop starts polling
@ -647,55 +672,65 @@ gdk_event_prepare (GSource *source,
*timeout = -1;
if (_gdk_display->event_pause_count > 0)
retval = _gdk_event_queue_find_first (_gdk_display) != NULL;
if (event_source->display->event_pause_count > 0)
retval = _gdk_event_queue_find_first (event_source->display) != NULL;
else
retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
_gdk_quartz_event_loop_check_pending ());
retval = (_gdk_event_queue_find_first (event_source->display) != NULL ||
_gdk_macos_event_source_check_pending ());
return retval;
}
static gboolean
gdk_event_check (GSource *source)
gdk_macos_event_source_check (GSource *source)
{
GdkMacosEventSource *event_source = (GdkMacosEventSource *)source;
gboolean retval;
if (_gdk_display->event_pause_count > 0)
retval = _gdk_event_queue_find_first (_gdk_display) != NULL;
if (event_source->display->event_pause_count > 0)
retval = _gdk_event_queue_find_first (event_source->display) != NULL;
else
retval = (_gdk_event_queue_find_first (_gdk_display) != NULL ||
_gdk_quartz_event_loop_check_pending ());
retval = (_gdk_event_queue_find_first (event_source->display) != NULL ||
_gdk_macos_event_source_check_pending ());
return retval;
}
static gboolean
gdk_event_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
gdk_macos_event_source_dispatch (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
GdkMacosEventSource *event_source = (GdkMacosEventSource *)source;
GdkEvent *event;
_gdk_quartz_display_queue_events (_gdk_display);
_gdk_macos_display_queue_events (GDK_MACOS_DISPLAY (event_source->display));
event = _gdk_event_unqueue (_gdk_display);
event = _gdk_event_unqueue (event_source->display);
if (event)
{
_gdk_event_emit (event);
g_object_unref (event);
gdk_event_unref (event);
}
return TRUE;
}
static void
gdk_macos_event_source_finalize (GSource *source)
{
GdkMacosEventSource *event_source = (GdkMacosEventSource *)source;
g_clear_object (&event_source->display);
}
static GSourceFuncs event_funcs = {
gdk_event_prepare,
gdk_event_check,
gdk_event_dispatch,
NULL
gdk_macos_event_source_prepare,
gdk_macos_event_source_check,
gdk_macos_event_source_dispatch,
gdk_macos_event_source_finalize,
};
/************************************************************
@ -704,8 +739,8 @@ static GSourceFuncs event_funcs = {
static gint
poll_func (GPollFD *ufds,
guint nfds,
gint timeout_)
guint nfds,
gint timeout_)
{
NSEvent *event;
NSDate *limit_date;
@ -727,9 +762,9 @@ poll_func (GPollFD *ufds,
limit_date = [NSDate dateWithTimeIntervalSinceNow:timeout_/1000.0];
getting_events++;
event = [NSApp nextEventMatchingMask: NSAnyEventMask
untilDate: limit_date
inMode: NSDefaultRunLoopMode
event = [NSApp nextEventMatchingMask: NSEventMaskAny
untilDate: limit_date
inMode: NSDefaultRunLoopMode
dequeue: YES];
getting_events--;
@ -744,10 +779,10 @@ poll_func (GPollFD *ufds,
*/
if (last_ufds == ufds && n_ready < 0)
n_ready = select_thread_collect_poll (ufds, nfds);
if (event &&
[event type] == NSApplicationDefined &&
[event subtype] == GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP)
[event type] == NSEventTypeApplicationDefined &&
[event subtype] == GDK_MACOS_EVENT_SUBTYPE_EVENTLOOP)
{
/* Just used to wake us up; if an event and a FD arrived at the same
* time; could have come from a previous iteration in some cases,
@ -756,7 +791,7 @@ poll_func (GPollFD *ufds,
event = NULL;
}
if (event)
if (event)
{
if (!current_events)
current_events = g_queue_new ();
@ -775,11 +810,11 @@ poll_func (GPollFD *ufds,
*/
static gint
query_main_context (GMainContext *context,
int max_priority,
int *timeout)
int max_priority,
int *timeout)
{
gint nfds;
if (!run_loop_pollfds)
{
run_loop_pollfds_size = RUN_LOOP_POLLFDS_INITIAL_SIZE;
@ -787,8 +822,8 @@ query_main_context (GMainContext *context,
}
while ((nfds = g_main_context_query (context, max_priority, timeout,
run_loop_pollfds,
run_loop_pollfds_size)) > run_loop_pollfds_size)
run_loop_pollfds,
run_loop_pollfds_size)) > run_loop_pollfds_size)
{
g_free (run_loop_pollfds);
run_loop_pollfds_size = nfds;
@ -804,24 +839,24 @@ run_loop_entry (void)
if (acquired_loop_level == -1)
{
if (g_main_context_acquire (NULL))
{
GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Beginning tracking run loop activity"));
acquired_loop_level = current_loop_level;
}
{
GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Beginning tracking run loop activity"));
acquired_loop_level = current_loop_level;
}
else
{
/* If we fail to acquire the main context, that means someone is iterating
* the main context in a different thread; we simply wait until this loop
* exits and then try again at next entry. In general, iterating the loop
* from a different thread is rare: it is only possible when GDK threading
* is initialized and is not frequently used even then. So, we hope that
* having GLib main loop iteration blocked in the combination of that and
* a native modal operation is a minimal problem. We could imagine using a
* thread that does g_main_context_wait() and then wakes us back up, but
* the gain doesn't seem worth the complexity.
*/
GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Can't acquire main loop; skipping tracking run loop activity"));
}
{
/* If we fail to acquire the main context, that means someone is iterating
* the main context in a different thread; we simply wait until this loop
* exits and then try again at next entry. In general, iterating the loop
* from a different thread is rare: it is only possible when GDK threading
* is initialized and is not frequently used even then. So, we hope that
* having GLib main loop iteration blocked in the combination of that and
* a native modal operation is a minimal problem. We could imagine using a
* thread that does g_main_context_wait() and then wakes us back up, but
* the gain doesn't seem worth the complexity.
*/
GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Can't acquire main loop; skipping tracking run loop activity"));
}
}
}
@ -844,8 +879,8 @@ run_loop_before_sources (void)
* sources are processed by the CFRunLoop, then processing will continue
* on to the BeforeWaiting stage where we check for lower priority sources.
*/
g_main_context_prepare (context, &max_priority);
g_main_context_prepare (context, &max_priority);
max_priority = MIN (max_priority, G_PRIORITY_DEFAULT);
/* We ignore the timeout that query_main_context () returns since we'll
@ -855,7 +890,7 @@ run_loop_before_sources (void)
if (nfds)
old_poll_func (run_loop_pollfds, nfds, 0);
if (g_main_context_check (context, max_priority, run_loop_pollfds, nfds))
{
GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Dispatching high priority sources"));
@ -865,7 +900,7 @@ run_loop_before_sources (void)
static void
dummy_timer_callback (CFRunLoopTimerRef timer,
void *info)
void *info)
{
/* Nothing; won't normally even be called */
}
@ -883,9 +918,9 @@ run_loop_before_waiting (void)
* go ahead and sleep. Before doing that, if there was a timeout from
* GLib, we set up a CFRunLoopTimer to wake us up.
*/
g_main_context_prepare (context, &run_loop_max_priority);
g_main_context_prepare (context, &run_loop_max_priority);
run_loop_n_pollfds = query_main_context (context, run_loop_max_priority, &timeout);
n_ready = select_thread_start_poll (run_loop_pollfds, run_loop_n_pollfds, timeout);
@ -902,18 +937,18 @@ run_loop_before_waiting (void)
* after the wait wakes up.
*/
GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Adding timer to wake us up in %d milliseconds", timeout));
run_loop_timer = CFRunLoopTimerCreate (NULL, /* allocator */
CFAbsoluteTimeGetCurrent () + timeout / 1000.,
0, /* interval (0=does not repeat) */
0, /* flags */
0, /* order (priority) */
dummy_timer_callback,
NULL);
CFAbsoluteTimeGetCurrent () + timeout / 1000.,
0, /* interval (0=does not repeat) */
0, /* flags */
0, /* order (priority) */
dummy_timer_callback,
NULL);
CFRunLoopAddTimer (main_thread_run_loop, run_loop_timer, kCFRunLoopCommonModes);
}
run_loop_polling_async = n_ready < 0;
}
@ -932,13 +967,13 @@ run_loop_after_waiting (void)
CFRelease (run_loop_timer);
run_loop_timer = NULL;
}
if (run_loop_polling_async)
{
select_thread_collect_poll (run_loop_pollfds, run_loop_n_pollfds);
run_loop_polling_async = FALSE;
}
if (g_main_context_check (context, run_loop_max_priority, run_loop_pollfds, run_loop_n_pollfds))
{
GDK_NOTE (EVENTLOOP, g_message ("EventLoop: Dispatching after waiting"));
@ -960,8 +995,8 @@ run_loop_exit (void)
static void
run_loop_observer_callback (CFRunLoopObserverRef observer,
CFRunLoopActivity activity,
void *info)
CFRunLoopActivity activity,
void *info)
{
switch (activity)
{
@ -972,6 +1007,11 @@ run_loop_observer_callback (CFRunLoopObserverRef observer,
g_return_if_fail (current_loop_level > 0);
current_loop_level--;
break;
case kCFRunLoopBeforeTimers:
case kCFRunLoopBeforeSources:
case kCFRunLoopBeforeWaiting:
case kCFRunLoopAfterWaiting:
case kCFRunLoopAllActivities:
default:
break;
}
@ -999,6 +1039,8 @@ run_loop_observer_callback (CFRunLoopObserverRef observer,
case kCFRunLoopExit:
run_loop_exit ();
break;
case kCFRunLoopAllActivities:
/* TODO: Do most of the above? */
default:
break;
}
@ -1006,41 +1048,47 @@ run_loop_observer_callback (CFRunLoopObserverRef observer,
/************************************************************/
void
_gdk_quartz_event_loop_init (void)
GSource *
_gdk_macos_event_source_new (GdkMacosDisplay *display)
{
GSource *source;
CFRunLoopObserverRef observer;
GdkMacosEventSource *event_source;
GSource *source;
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
/* Hook into the GLib main loop */
event_poll_fd.events = G_IO_IN;
event_poll_fd.fd = -1;
source = g_source_new (&event_funcs, sizeof (GSource));
g_source_set_name (source, "GDK Quartz event source");
source = g_source_new (&event_funcs, sizeof (GdkMacosEventSource));
g_source_set_name (source, "GDK Quartz event source");
g_source_add_poll (source, &event_poll_fd);
g_source_set_priority (source, GDK_PRIORITY_EVENTS);
g_source_set_can_recurse (source, TRUE);
g_source_attach (source, NULL);
old_poll_func = g_main_context_get_poll_func (NULL);
g_main_context_set_poll_func (NULL, poll_func);
event_source = (GdkMacosEventSource *)source;
event_source->display = g_object_ref (GDK_DISPLAY (display));
/* Hook into the the CFRunLoop for the main thread */
main_thread_run_loop = CFRunLoopGetCurrent ();
observer = CFRunLoopObserverCreate (NULL, /* default allocator */
kCFRunLoopAllActivities,
true, /* repeats: not one-shot */
0, /* order (priority) */
run_loop_observer_callback,
NULL);
CFRunLoopAddObserver (main_thread_run_loop, observer, kCFRunLoopCommonModes);
/* Initialize our autorelease pool */
kCFRunLoopAllActivities,
true, /* repeats: not one-shot */
0, /* order (priority) */
run_loop_observer_callback,
NULL);
CFRunLoopAddObserver (main_thread_run_loop, observer, kCFRunLoopCommonModes);
/* Initialize our autorelease pool */
autorelease_pool = [[NSAutoreleasePool alloc] init];
return source;
}

View File

@ -0,0 +1,60 @@
/* gdkmacosglcontext-private.h
*
* Copyright (C) 2020 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_MACOS_GL_CONTEXT_PRIVATE_H__
#define __GDK_MACOS_GL_CONTEXT_PRIVATE_H__
#include "gdkglcontextprivate.h"
#include "gdkdisplayprivate.h"
#include "gdksurface.h"
#include "gdkinternals.h"
#include "gdkmacosglcontext.h"
#include "gdkmacossurface.h"
#import <OpenGL/OpenGL.h>
#import <OpenGL/gl.h>
#import <AppKit/AppKit.h>
G_BEGIN_DECLS
struct _GdkMacosGLContext
{
GdkGLContext parent_instance;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
NSOpenGLContext *gl_context;
G_GNUC_END_IGNORE_DEPRECATIONS
gboolean is_attached;
};
struct _GdkMacosGLContextClass
{
GdkGLContextClass parent_class;
};
GdkGLContext *_gdk_macos_gl_context_new (GdkMacosSurface *surface,
gboolean attached,
GdkGLContext *share,
GError **error);
gboolean _gdk_macos_gl_context_make_current (GdkMacosGLContext *self);
G_END_DECLS
#endif /* __GDK_MACOS_GL_CONTEXT_PRIVATE_H__ */

View File

@ -0,0 +1,153 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include "gdkmacosglcontext-private.h"
#include "gdkmacossurface-private.h"
#include "gdkinternals.h"
#include "gdkintl.h"
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
G_DEFINE_TYPE (GdkMacosGLContext, gdk_macos_gl_context, GDK_TYPE_GL_CONTEXT)
static void
gdk_macos_gl_context_end_frame (GdkDrawContext *context,
cairo_region_t *painted)
{
GdkMacosGLContext *self = GDK_MACOS_GL_CONTEXT (context);
g_assert (GDK_IS_MACOS_GL_CONTEXT (self));
[self->gl_context flushBuffer];
}
static void
gdk_macos_gl_context_dispose (GObject *gobject)
{
GdkMacosGLContext *context_macos = GDK_MACOS_GL_CONTEXT (gobject);
if (context_macos->gl_context != NULL)
{
[context_macos->gl_context clearDrawable];
[context_macos->gl_context release];
context_macos->gl_context = NULL;
}
G_OBJECT_CLASS (gdk_macos_gl_context_parent_class)->dispose (gobject);
}
static void
gdk_macos_gl_context_class_init (GdkMacosGLContextClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
object_class->dispose = gdk_macos_gl_context_dispose;
draw_context_class->end_frame = gdk_macos_gl_context_end_frame;
}
static void
gdk_macos_gl_context_init (GdkMacosGLContext *self)
{
}
GdkGLContext *
_gdk_macos_gl_context_new (GdkMacosSurface *surface,
gboolean attached,
GdkGLContext *share,
GError **error)
{
static const NSOpenGLPixelFormatAttribute attrs[] = {
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
0
};
NSOpenGLPixelFormat *format;
GdkMacosGLContext *context = NULL;
NSOpenGLContext *ctx;
GdkDisplay *display;
NSView *nsview;
GLint sync_to_framerate = 1;
g_return_val_if_fail (GDK_IS_MACOS_SURFACE (surface), NULL);
g_return_val_if_fail (!share || GDK_IS_MACOS_GL_CONTEXT (share), NULL);
display = gdk_surface_get_display (GDK_SURFACE (surface));
if (!(format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]))
{
g_set_error_literal (error,
GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("Unable to create a GL pixel format"));
goto failure;
}
ctx = [[NSOpenGLContext alloc] initWithFormat:format
shareContext:share ? GDK_MACOS_GL_CONTEXT (share)->gl_context : nil];
if (ctx == NULL)
{
g_set_error_literal (error,
GDK_GL_ERROR,
GDK_GL_ERROR_NOT_AVAILABLE,
_("Unable to create a GL context"));
goto failure;
}
nsview = _gdk_macos_surface_get_view (surface);
[nsview setWantsBestResolutionOpenGLSurface:YES];
[ctx setValues:&sync_to_framerate forParameter:NSOpenGLCPSwapInterval];
[ctx setView:nsview];
GDK_NOTE (OPENGL,
g_print ("Created NSOpenGLContext[%p]\n", ctx));
context = g_object_new (GDK_TYPE_MACOS_GL_CONTEXT,
"surface", surface,
"shared-context", share,
NULL);
context->gl_context = ctx;
context->is_attached = attached;
failure:
if (format != NULL)
[format release];
return GDK_GL_CONTEXT (context);
}
gboolean
_gdk_macos_gl_context_make_current (GdkMacosGLContext *self)
{
g_return_val_if_fail (GDK_IS_MACOS_GL_CONTEXT (self), FALSE);
[self->gl_context makeCurrentContext];
return TRUE;
}
G_GNUC_END_IGNORE_DEPRECATIONS

View File

@ -0,0 +1,43 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_GL_CONTEXT_H__
#define __GDK_MACOS_GL_CONTEXT_H__
#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/macos/gdkmacos.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
#define GDK_TYPE_MACOS_GL_CONTEXT (gdk_macos_gl_context_get_type ())
#define GDK_MACOS_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_MACOS_GL_CONTEXT, GdkMacosGLContext))
#define GDK_IS_MACOS_GL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_MACOS_GL_CONTEXT))
typedef struct _GdkMacosGLContext GdkMacosGLContext;
typedef struct _GdkMacosGLContextClass GdkMacosGLContextClass;
GDK_AVAILABLE_IN_ALL
GType gdk_macos_gl_context_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GDK_MACOS_GL_CONTEXT_H__ */

View File

@ -0,0 +1,36 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_KEYMAP_PRIVATE_H__
#define __GDK_MACOS_KEYMAP_PRIVATE_H__
#include <AppKit/AppKit.h>
#include "gdkmacosdisplay.h"
#include "gdkmacoskeymap.h"
G_BEGIN_DECLS
GdkMacosKeymap *_gdk_macos_keymap_new (GdkMacosDisplay *display);
GdkEventType _gdk_macos_keymap_get_event_type (NSEvent *event);
gboolean _gdk_macos_keymap_is_modifier (guint keycode);
G_END_DECLS
#endif /* __GDK_MACOS_KEYMAP_PRIVATE_H__ */

698
gdk/macos/gdkmacoskeymap.c Normal file
View File

@ -0,0 +1,698 @@
/*
* Copyright © 2000-2020 Red Hat, Inc.
* Copyright © 2005 Imendio AB
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
/* Some parts of this code come from quartzKeyboard.c,
* from the Apple X11 Server.
*
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
* HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name(s) of the above
* copyright holders shall not be used in advertising or otherwise to
* promote the sale, use or other dealings in this Software without
* prior written authorization.
*/
#include "config.h"
#include <AppKit/AppKit.h>
#include <Carbon/Carbon.h>
#include <gdk/gdk.h>
#include "gdkkeysprivate.h"
#include "gdkkeysyms.h"
#include "gdkmacoskeymap-private.h"
struct _GdkMacosKeymap
{
GdkKeymap parent_instance;
};
struct _GdkMacosKeymapClass
{
GdkKeymapClass parent_instance;
};
G_DEFINE_TYPE (GdkMacosKeymap, gdk_macos_keymap, GDK_TYPE_KEYMAP)
/* This is a table of all keyvals. Each keycode gets KEYVALS_PER_KEYCODE entries.
* TThere is 1 keyval per modifier (Nothing, Shift, Alt, Shift+Alt);
*/
static guint *keyval_array = NULL;
#define NUM_KEYCODES 128
#define KEYVALS_PER_KEYCODE 4
#define GET_KEYVAL(keycode, group, level) \
(keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
const static struct {
guint keycode;
guint keyval;
unsigned int modmask; /* So we can tell when a mod key is pressed/released */
} modifier_keys[] = {
{ 54, GDK_KEY_Meta_R, NSEventModifierFlagCommand },
{ 55, GDK_KEY_Meta_L, NSEventModifierFlagCommand },
{ 56, GDK_KEY_Shift_L, NSEventModifierFlagShift },
{ 57, GDK_KEY_Caps_Lock, NSEventModifierFlagCapsLock },
{ 58, GDK_KEY_Alt_L, NSEventModifierFlagOption },
{ 59, GDK_KEY_Control_L, NSEventModifierFlagControl },
{ 60, GDK_KEY_Shift_R, NSEventModifierFlagShift },
{ 61, GDK_KEY_Alt_R, NSEventModifierFlagOption },
{ 62, GDK_KEY_Control_R, NSEventModifierFlagControl }
};
const static struct {
guint keycode;
guint keyval;
} function_keys[] = {
{ 122, GDK_KEY_F1 },
{ 120, GDK_KEY_F2 },
{ 99, GDK_KEY_F3 },
{ 118, GDK_KEY_F4 },
{ 96, GDK_KEY_F5 },
{ 97, GDK_KEY_F6 },
{ 98, GDK_KEY_F7 },
{ 100, GDK_KEY_F8 },
{ 101, GDK_KEY_F9 },
{ 109, GDK_KEY_F10 },
{ 103, GDK_KEY_F11 },
{ 111, GDK_KEY_F12 },
{ 105, GDK_KEY_F13 },
{ 107, GDK_KEY_F14 },
{ 113, GDK_KEY_F15 },
{ 106, GDK_KEY_F16 }
};
const static struct {
guint keycode;
guint normal_keyval, keypad_keyval;
} known_numeric_keys[] = {
{ 65, GDK_KEY_period, GDK_KEY_KP_Decimal },
{ 67, GDK_KEY_asterisk, GDK_KEY_KP_Multiply },
{ 69, GDK_KEY_plus, GDK_KEY_KP_Add },
{ 75, GDK_KEY_slash, GDK_KEY_KP_Divide },
{ 76, GDK_KEY_Return, GDK_KEY_KP_Enter },
{ 78, GDK_KEY_minus, GDK_KEY_KP_Subtract },
{ 81, GDK_KEY_equal, GDK_KEY_KP_Equal },
{ 82, GDK_KEY_0, GDK_KEY_KP_0 },
{ 83, GDK_KEY_1, GDK_KEY_KP_1 },
{ 84, GDK_KEY_2, GDK_KEY_KP_2 },
{ 85, GDK_KEY_3, GDK_KEY_KP_3 },
{ 86, GDK_KEY_4, GDK_KEY_KP_4 },
{ 87, GDK_KEY_5, GDK_KEY_KP_5 },
{ 88, GDK_KEY_6, GDK_KEY_KP_6 },
{ 89, GDK_KEY_7, GDK_KEY_KP_7 },
{ 91, GDK_KEY_8, GDK_KEY_KP_8 },
{ 92, GDK_KEY_9, GDK_KEY_KP_9 }
};
/* These values aren't covered by gdk_unicode_to_keyval */
const static struct {
gunichar ucs_value;
guint keyval;
} special_ucs_table [] = {
{ 0x0001, GDK_KEY_Home },
{ 0x0003, GDK_KEY_Return },
{ 0x0004, GDK_KEY_End },
{ 0x0008, GDK_KEY_BackSpace },
{ 0x0009, GDK_KEY_Tab },
{ 0x000b, GDK_KEY_Page_Up },
{ 0x000c, GDK_KEY_Page_Down },
{ 0x000d, GDK_KEY_Return },
{ 0x001b, GDK_KEY_Escape },
{ 0x001c, GDK_KEY_Left },
{ 0x001d, GDK_KEY_Right },
{ 0x001e, GDK_KEY_Up },
{ 0x001f, GDK_KEY_Down },
{ 0x007f, GDK_KEY_Delete },
{ 0xf027, GDK_KEY_dead_acute },
{ 0xf060, GDK_KEY_dead_grave },
{ 0xf300, GDK_KEY_dead_grave },
{ 0xf0b4, GDK_KEY_dead_acute },
{ 0xf301, GDK_KEY_dead_acute },
{ 0xf385, GDK_KEY_dead_acute },
{ 0xf05e, GDK_KEY_dead_circumflex },
{ 0xf2c6, GDK_KEY_dead_circumflex },
{ 0xf302, GDK_KEY_dead_circumflex },
{ 0xf07e, GDK_KEY_dead_tilde },
{ 0xf2dc, GDK_KEY_dead_tilde },
{ 0xf303, GDK_KEY_dead_tilde },
{ 0xf342, GDK_KEY_dead_perispomeni },
{ 0xf0af, GDK_KEY_dead_macron },
{ 0xf304, GDK_KEY_dead_macron },
{ 0xf2d8, GDK_KEY_dead_breve },
{ 0xf306, GDK_KEY_dead_breve },
{ 0xf2d9, GDK_KEY_dead_abovedot },
{ 0xf307, GDK_KEY_dead_abovedot },
{ 0xf0a8, GDK_KEY_dead_diaeresis },
{ 0xf308, GDK_KEY_dead_diaeresis },
{ 0xf2da, GDK_KEY_dead_abovering },
{ 0xf30A, GDK_KEY_dead_abovering },
{ 0xf022, GDK_KEY_dead_doubleacute },
{ 0xf2dd, GDK_KEY_dead_doubleacute },
{ 0xf30B, GDK_KEY_dead_doubleacute },
{ 0xf2c7, GDK_KEY_dead_caron },
{ 0xf30C, GDK_KEY_dead_caron },
{ 0xf0be, GDK_KEY_dead_cedilla },
{ 0xf327, GDK_KEY_dead_cedilla },
{ 0xf2db, GDK_KEY_dead_ogonek },
{ 0xf328, GDK_KEY_dead_ogonek },
{ 0xfe5d, GDK_KEY_dead_iota },
{ 0xf323, GDK_KEY_dead_belowdot },
{ 0xf309, GDK_KEY_dead_hook },
{ 0xf31B, GDK_KEY_dead_horn },
{ 0xf02d, GDK_KEY_dead_stroke },
{ 0xf335, GDK_KEY_dead_stroke },
{ 0xf336, GDK_KEY_dead_stroke },
{ 0xf313, GDK_KEY_dead_abovecomma },
/* { 0xf313, GDK_KEY_dead_psili }, */
{ 0xf314, GDK_KEY_dead_abovereversedcomma },
/* { 0xf314, GDK_KEY_dead_dasia }, */
{ 0xf30F, GDK_KEY_dead_doublegrave },
{ 0xf325, GDK_KEY_dead_belowring },
{ 0xf2cd, GDK_KEY_dead_belowmacron },
{ 0xf331, GDK_KEY_dead_belowmacron },
{ 0xf32D, GDK_KEY_dead_belowcircumflex },
{ 0xf330, GDK_KEY_dead_belowtilde },
{ 0xf32E, GDK_KEY_dead_belowbreve },
{ 0xf324, GDK_KEY_dead_belowdiaeresis },
{ 0xf311, GDK_KEY_dead_invertedbreve },
{ 0xf02c, GDK_KEY_dead_belowcomma },
{ 0xf326, GDK_KEY_dead_belowcomma }
};
static void
gdk_macos_keymap_update (GdkMacosKeymap *self)
{
const void *chr_data = NULL;
guint *p;
int i;
TISInputSourceRef new_layout = TISCopyCurrentKeyboardLayoutInputSource ();
CFDataRef layout_data_ref;
g_free (keyval_array);
keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
layout_data_ref = (CFDataRef)TISGetInputSourceProperty (new_layout, kTISPropertyUnicodeKeyLayoutData);
if (layout_data_ref)
chr_data = CFDataGetBytePtr (layout_data_ref);
if (chr_data == NULL)
{
g_error ("cannot get keyboard layout data");
return;
}
for (i = 0; i < NUM_KEYCODES; i++)
{
int j;
UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
UniChar chars[4];
UniCharCount nChars;
p = keyval_array + i * KEYVALS_PER_KEYCODE;
for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
{
UInt32 state = 0;
OSStatus err;
UInt16 key_code;
UniChar uc;
key_code = modifiers[j] | i;
err = UCKeyTranslate (chr_data, i, kUCKeyActionDisplay,
(modifiers[j] >> 8) & 0xFF,
LMGetKbdType(),
0,
&state, 4, &nChars, chars);
/* FIXME: Theoretically, we can get multiple UTF-16
* values; we should convert them to proper unicode and
* figure out whether there are really keyboard layouts
* that give us more than one character for one
* keypress.
*/
if (err == noErr && nChars == 1)
{
int k;
gboolean found = FALSE;
/* A few <Shift><Option>keys return two characters,
* the first of which is U+00a0, which isn't
* interesting; so we return the second. More
* sophisticated handling is the job of a
* GtkIMContext.
*
* If state isn't zero, it means that it's a dead
* key of some sort. Some of those are enumerated in
* the special_ucs_table with the high nibble set to
* f to push it into the private use range. Here we
* do the same.
*/
if (state != 0)
chars[nChars - 1] |= 0xf000;
uc = chars[nChars - 1];
for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
{
if (special_ucs_table[k].ucs_value == uc)
{
p[j] = special_ucs_table[k].keyval;
found = TRUE;
break;
}
}
/* Special-case shift-tab since GTK+ expects
* GDK_KEY_ISO_Left_Tab for that.
*/
if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
p[j] = GDK_KEY_ISO_Left_Tab;
if (!found)
p[j] = gdk_unicode_to_keyval (uc);
}
}
if (p[3] == p[2])
p[3] = 0;
if (p[2] == p[1])
p[2] = 0;
if (p[1] == p[0])
p[1] = 0;
if (p[0] == p[2] &&
p[1] == p[3])
p[2] = p[3] = 0;
}
for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
{
p = keyval_array + modifier_keys[i].keycode * KEYVALS_PER_KEYCODE;
if (p[0] == 0 && p[1] == 0 &&
p[2] == 0 && p[3] == 0)
p[0] = modifier_keys[i].keyval;
}
for (i = 0; i < G_N_ELEMENTS (function_keys); i++)
{
p = keyval_array + function_keys[i].keycode * KEYVALS_PER_KEYCODE;
p[0] = function_keys[i].keyval;
p[1] = p[2] = p[3] = 0;
}
for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
{
p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
if (p[0] == known_numeric_keys[i].normal_keyval)
p[0] = known_numeric_keys[i].keypad_keyval;
}
g_signal_emit_by_name (self, "keys-changed");
}
static PangoDirection
gdk_macos_keymap_get_direction (GdkKeymap *keymap)
{
return PANGO_DIRECTION_NEUTRAL;
}
static gboolean
gdk_macos_keymap_have_bidi_layouts (GdkKeymap *keymap)
{
return FALSE;
}
static gboolean
gdk_macos_keymap_get_caps_lock_state (GdkKeymap *keymap)
{
return FALSE;
}
static gboolean
gdk_macos_keymap_get_num_lock_state (GdkKeymap *keymap)
{
return FALSE;
}
static gboolean
gdk_macos_keymap_get_scroll_lock_state (GdkKeymap *keymap)
{
return FALSE;
}
static guint
gdk_macos_keymap_lookup_key (GdkKeymap *keymap,
const GdkKeymapKey *key)
{
GdkMacosKeymap *self = (GdkMacosKeymap *)keymap;
g_assert (GDK_IS_MACOS_KEYMAP (self));
g_assert (key != NULL);
return GET_KEYVAL (key->keycode, key->group, key->level);
}
static guint
translate_keysym (guint hardware_keycode,
gint group,
GdkModifierType state,
gint *effective_group,
gint *effective_level)
{
gint level;
guint tmp_keyval;
level = (state & GDK_SHIFT_MASK) ? 1 : 0;
if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) &&
(GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1)))
group = 0;
if (!GET_KEYVAL (hardware_keycode, group, level) &&
GET_KEYVAL (hardware_keycode, group, 0))
level = 0;
tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
if (state & GDK_LOCK_MASK)
{
guint upper = gdk_keyval_to_upper (tmp_keyval);
if (upper != tmp_keyval)
tmp_keyval = upper;
}
if (effective_group)
*effective_group = group;
if (effective_level)
*effective_level = level;
return tmp_keyval;
}
static gboolean
gdk_macos_keymap_get_entries_for_keyval (GdkKeymap *keymap,
guint keyval,
GArray *keys)
{
gboolean ret = FALSE;
g_assert (GDK_IS_MACOS_KEYMAP (keymap));
g_assert (keys != NULL);
for (guint i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
{
GdkKeymapKey key;
if (keyval_array[i] != keyval)
continue;
key.keycode = i / KEYVALS_PER_KEYCODE;
key.group = (i % KEYVALS_PER_KEYCODE) >= 2;
key.level = i % 2;
g_array_append_val (keys, key);
ret = TRUE;
}
return ret;
}
static gboolean
gdk_macos_keymap_get_entries_for_keycode (GdkKeymap *keymap,
guint hardware_keycode,
GdkKeymapKey **keys,
guint **keyvals,
gint *n_entries)
{
GArray *keys_array;
GArray *keyvals_array;
guint *p;
guint i;
g_assert (GDK_IS_MACOS_KEYMAP (keymap));
g_assert (keyvals != NULL);
g_assert (n_entries != NULL);
*keyvals = NULL;
*n_entries = 0;
if (hardware_keycode > NUM_KEYCODES)
return FALSE;
if (keys)
keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
else
keys_array = NULL;
if (keyvals)
keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
else
keyvals_array = NULL;
p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
{
if (!p[i])
continue;
(*n_entries)++;
if (keyvals_array)
g_array_append_val (keyvals_array, p[i]);
if (keys_array)
{
GdkKeymapKey key;
key.keycode = hardware_keycode;
key.group = i >= 2;
key.level = i % 2;
g_array_append_val (keys_array, key);
}
}
if (keys)
*keys = (GdkKeymapKey *)(gpointer)g_array_free (keys_array, FALSE);
if (keyvals)
*keyvals = (guint *)(gpointer)g_array_free (keyvals_array, FALSE);
return *n_entries > 0;
}
static gboolean
gdk_macos_keymap_translate_keyboard_state (GdkKeymap *keymap,
guint hardware_keycode,
GdkModifierType state,
gint group,
guint *keyval,
gint *effective_group,
gint *level,
GdkModifierType *consumed_modifiers)
{
guint tmp_keyval;
GdkModifierType bit;
g_assert (GDK_IS_MACOS_KEYMAP (keymap));
if (keyval)
*keyval = 0;
if (effective_group)
*effective_group = 0;
if (level)
*level = 0;
if (consumed_modifiers)
*consumed_modifiers = 0;
if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
return FALSE;
tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
/* Check if modifiers modify the keyval */
if (consumed_modifiers)
{
guint tmp_modifiers = (state & GDK_MODIFIER_MASK);
for (bit = 1; bit <= tmp_modifiers; bit <<= 1)
{
if ((bit & tmp_modifiers) &&
translate_keysym (hardware_keycode, group, state & ~bit,
NULL, NULL) == tmp_keyval)
tmp_modifiers &= ~bit;
}
*consumed_modifiers = tmp_modifiers;
}
if (keyval)
*keyval = tmp_keyval;
return TRUE;
}
static void
input_sources_changed_notification (CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
GdkMacosKeymap *self = observer;
g_assert (GDK_IS_MACOS_KEYMAP (self));
gdk_macos_keymap_update (self);
}
static void
gdk_macos_keymap_finalize (GObject *object)
{
CFNotificationCenterRemoveObserver (CFNotificationCenterGetDistributedCenter (),
object,
CFSTR ("AppleSelectedInputSourcesChangedNotification"),
NULL);
G_OBJECT_CLASS (gdk_macos_keymap_parent_class)->finalize (object);
}
static void
gdk_macos_keymap_class_init (GdkMacosKeymapClass *klass)
{
GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gdk_macos_keymap_finalize;
keymap_class->get_caps_lock_state = gdk_macos_keymap_get_caps_lock_state;
keymap_class->get_direction = gdk_macos_keymap_get_direction;
keymap_class->get_entries_for_keycode = gdk_macos_keymap_get_entries_for_keycode;
keymap_class->get_entries_for_keyval = gdk_macos_keymap_get_entries_for_keyval;
keymap_class->get_num_lock_state = gdk_macos_keymap_get_num_lock_state;
keymap_class->get_scroll_lock_state = gdk_macos_keymap_get_scroll_lock_state;
keymap_class->have_bidi_layouts = gdk_macos_keymap_have_bidi_layouts;
keymap_class->lookup_key = gdk_macos_keymap_lookup_key;
keymap_class->translate_keyboard_state = gdk_macos_keymap_translate_keyboard_state;
}
static void
gdk_macos_keymap_init (GdkMacosKeymap *self)
{
CFNotificationCenterAddObserver (CFNotificationCenterGetDistributedCenter (),
self,
input_sources_changed_notification,
CFSTR ("AppleSelectedInputSourcesChangedNotification"),
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
gdk_macos_keymap_update (self);
}
GdkMacosKeymap *
_gdk_macos_keymap_new (GdkMacosDisplay *display)
{
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
return g_object_new (GDK_TYPE_MACOS_KEYMAP,
"display", display,
NULL);
}
/* What sort of key event is this? Returns one of
* GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
*/
GdkEventType
_gdk_macos_keymap_get_event_type (NSEvent *event)
{
unsigned short keycode;
unsigned int flags;
switch ((int)[event type])
{
case NSEventTypeKeyDown:
return GDK_KEY_PRESS;
case NSEventTypeKeyUp:
return GDK_KEY_RELEASE;
case NSEventTypeFlagsChanged:
break;
default:
g_assert_not_reached ();
}
/* For flags-changed events, we have to find the special key that caused the
* event, and see if it's in the modifier mask. */
keycode = [event keyCode];
flags = [event modifierFlags];
for (guint i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
{
if (modifier_keys[i].keycode == keycode)
{
if (flags & modifier_keys[i].modmask)
return GDK_KEY_PRESS;
else
return GDK_KEY_RELEASE;
}
}
/* Some keypresses (eg: Expose' activations) seem to trigger flags-changed
* events for no good reason. Ignore them! */
return 0;
}
gboolean
_gdk_macos_keymap_is_modifier (guint keycode)
{
for (guint i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
{
if (modifier_keys[i].modmask == 0)
break;
if (modifier_keys[i].keycode == keycode)
return TRUE;
}
return FALSE;
}

View File

@ -0,0 +1,43 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_KEYMAP_H__
#define __GDK_MACOS_KEYMAP_H__
#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/macos/gdkmacos.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
typedef struct _GdkMacosKeymap GdkMacosKeymap;
typedef struct _GdkMacosKeymapClass GdkMacosKeymapClass;
#define GDK_TYPE_MACOS_KEYMAP (gdk_macos_keymap_get_type())
#define GDK_MACOS_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_KEYMAP, GdkMacosKeymap))
#define GDK_IS_MACOS_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_KEYMAP))
GDK_AVAILABLE_IN_ALL
GType gdk_macos_keymap_get_type (void);
G_END_DECLS
#endif /* __GDK_MACOS_KEYMAP_H__ */

View File

@ -0,0 +1,39 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_MONITOR_PRIVATE_H__
#define __GDK_MACOS_MONITOR_PRIVATE_H__
#include <AppKit/AppKit.h>
#include "gdkmacosdisplay.h"
#include "gdkmacosmonitor.h"
#include "gdkmonitorprivate.h"
G_BEGIN_DECLS
GdkMacosMonitor *_gdk_macos_monitor_new (GdkMacosDisplay *display,
CGDirectDisplayID screen_id);
CGDirectDisplayID _gdk_macos_monitor_get_screen_id (GdkMacosMonitor *self);
gboolean _gdk_macos_monitor_reconfigure (GdkMacosMonitor *self);
G_END_DECLS
#endif /* __GDK_MACOS_MONITOR_PRIVATE_H__ */

288
gdk/macos/gdkmacosmonitor.c Normal file
View File

@ -0,0 +1,288 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include <gdk/gdk.h>
#include <math.h>
#include "gdkmacosdisplay-private.h"
#include "gdkmacosmonitor-private.h"
#include "gdkmacosutils-private.h"
struct _GdkMacosMonitor
{
GdkMonitor parent_instance;
CGDirectDisplayID screen_id;
NSRect workarea;
guint has_opengl : 1;
};
struct _GdkMacosMonitorClass
{
GdkMonitorClass parent_class;
};
G_DEFINE_TYPE (GdkMacosMonitor, gdk_macos_monitor, GDK_TYPE_MONITOR)
static void
gdk_macos_monitor_get_workarea (GdkMonitor *monitor,
GdkRectangle *geometry)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkMacosMonitor *self = (GdkMacosMonitor *)monitor;
int x, y;
g_assert (GDK_IS_MACOS_MONITOR (self));
g_assert (geometry != NULL);
x = self->workarea.origin.x;
y = self->workarea.origin.y + self->workarea.size.height;
_gdk_macos_display_from_display_coords (GDK_MACOS_DISPLAY (monitor->display),
x, y,
&x, &y);
geometry->x = x;
geometry->y = y;
geometry->width = self->workarea.size.width;
geometry->height = self->workarea.size.height;
GDK_END_MACOS_ALLOC_POOL;
}
static void
gdk_macos_monitor_class_init (GdkMacosMonitorClass *klass)
{
GdkMonitorClass *monitor_class = GDK_MONITOR_CLASS (klass);
monitor_class->get_workarea = gdk_macos_monitor_get_workarea;
}
static void
gdk_macos_monitor_init (GdkMacosMonitor *self)
{
}
static GdkSubpixelLayout
GetSubpixelLayout (CGDirectDisplayID screen_id)
{
#if 0
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkSubpixelLayout subpixel_layout = GDK_SUBPIXEL_LAYOUT_UNKNOWN;
io_service_t iosvc;
NSDictionary *dict;
guint layout;
gboolean rotation;
rotation = CGDisplayRotation (screen_id);
iosvc = CGDisplayIOServicePort (screen_id);
dict = (NSDictionary *)IODisplayCreateInfoDictionary (iosvc, kIODisplayOnlyPreferredName);
layout = [[dict objectForKey:@kDisplaySubPixelLayout] unsignedIntValue];
switch (layout)
{
case kDisplaySubPixelLayoutRGB:
if (rotation == 0.0)
subpixel_layout = GDK_SUBPIXEL_LAYOUT_HORIZONTAL_RGB;
else if (rotation == 90.0)
subpixel_layout = GDK_SUBPIXEL_LAYOUT_VERTICAL_RGB;
else if (rotation == 180.0 || rotation == -180.0)
subpixel_layout = GDK_SUBPIXEL_LAYOUT_HORIZONTAL_BGR;
else if (rotation == -90.0)
subpixel_layout = GDK_SUBPIXEL_LAYOUT_VERTICAL_BGR;
break;
case kDisplaySubPixelLayoutBGR:
if (rotation == 0.0)
subpixel_layout = GDK_SUBPIXEL_LAYOUT_HORIZONTAL_BGR;
else if (rotation == 90.0)
subpixel_layout = GDK_SUBPIXEL_LAYOUT_VERTICAL_BGR;
else if (rotation == 180.0 || rotation == -180.0)
subpixel_layout = GDK_SUBPIXEL_LAYOUT_HORIZONTAL_RGB;
else if (rotation == -90.0 || rotation == 270.0)
subpixel_layout = GDK_SUBPIXEL_LAYOUT_VERTICAL_RGB;
break;
default:
break;
}
GDK_END_MACOS_ALLOC_POOL;
return subpixel_layout;
#endif
return GDK_SUBPIXEL_LAYOUT_UNKNOWN;
}
static char *
GetLocalizedName (NSScreen *screen)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
NSString *str;
char *name;
g_assert (screen);
str = [screen localizedName];
name = g_strdup ([str UTF8String]);
GDK_END_MACOS_ALLOC_POOL;
return g_steal_pointer (&name);
}
static gchar *
GetConnectorName (CGDirectDisplayID screen_id)
{
guint unit = CGDisplayUnitNumber (screen_id);
return g_strdup_printf ("unit-%u", unit);
}
static NSScreen *
find_screen (CGDirectDisplayID screen_id)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
NSScreen *screen = NULL;
for (id obj in [NSScreen screens])
{
if (screen_id == [[[obj deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue])
{
screen = (NSScreen *)obj;
break;
}
}
GDK_END_MACOS_ALLOC_POOL;
return screen;
}
gboolean
_gdk_macos_monitor_reconfigure (GdkMacosMonitor *self)
{
GdkSubpixelLayout subpixel_layout;
CGDisplayModeRef mode;
GdkMacosDisplay *display;
NSScreen *screen;
GdkRectangle geom;
gboolean has_opengl;
CGSize size;
CGRect bounds;
size_t width;
size_t pixel_width;
gchar *connector;
gchar *name;
int refresh_rate;
int scale_factor = 1;
int width_mm;
int height_mm;
g_return_val_if_fail (GDK_IS_MACOS_MONITOR (self), FALSE);
display = GDK_MACOS_DISPLAY (GDK_MONITOR (self)->display);
if (!(screen = find_screen (self->screen_id)) ||
!(mode = CGDisplayCopyDisplayMode (self->screen_id)))
return FALSE;
size = CGDisplayScreenSize (self->screen_id);
bounds = [screen frame];
width = CGDisplayModeGetWidth (mode);
pixel_width = CGDisplayModeGetPixelWidth (mode);
has_opengl = CGDisplayUsesOpenGLAcceleration (self->screen_id);
subpixel_layout = GetSubpixelLayout (self->screen_id);
name = GetLocalizedName (screen);
connector = GetConnectorName (self->screen_id);
if (width != 0 && pixel_width != 0)
scale_factor = MAX (1, pixel_width / width);
width_mm = size.width;
height_mm = size.height;
geom.x = bounds.origin.x - display->min_x;
geom.y = display->height - bounds.origin.y - bounds.size.height + display->min_y;
geom.width = bounds.size.width;
geom.height = bounds.size.height;
/* We will often get 0 back from CGDisplayModeGetRefreshRate(). We
* can fallback by getting it from CoreVideo based on a CVDisplayLink
* setting (which is also used by the frame clock).
*/
if (!(refresh_rate = CGDisplayModeGetRefreshRate (mode)))
refresh_rate = _gdk_macos_display_get_nominal_refresh_rate (display);
gdk_monitor_set_connector (GDK_MONITOR (self), connector);
gdk_monitor_set_model (GDK_MONITOR (self), name);
gdk_monitor_set_geometry (GDK_MONITOR (self), &geom);
gdk_monitor_set_physical_size (GDK_MONITOR (self), width_mm, height_mm);
gdk_monitor_set_scale_factor (GDK_MONITOR (self), scale_factor);
gdk_monitor_set_refresh_rate (GDK_MONITOR (self), refresh_rate);
gdk_monitor_set_subpixel_layout (GDK_MONITOR (self), GDK_SUBPIXEL_LAYOUT_UNKNOWN);
self->workarea = [screen visibleFrame];
/* We might be able to use this at some point to change which GSK renderer
* we use for surfaces on this monitor. For example, it might be better
* to use cairo if we cannot use OpenGL (or it would be software) anyway.
* Presumably that is more common in cases where macOS is running under
* an emulator such as QEMU.
*/
self->has_opengl = !!has_opengl;
CGDisplayModeRelease (mode);
g_free (name);
g_free (connector);
return TRUE;
}
GdkMacosMonitor *
_gdk_macos_monitor_new (GdkMacosDisplay *display,
CGDirectDisplayID screen_id)
{
GdkMacosMonitor *self;
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
self = g_object_new (GDK_TYPE_MACOS_MONITOR,
"display", display,
NULL);
self->screen_id = screen_id;
_gdk_macos_monitor_reconfigure (self);
return g_steal_pointer (&self);
}
CGDirectDisplayID
_gdk_macos_monitor_get_screen_id (GdkMacosMonitor *self)
{
g_return_val_if_fail (GDK_IS_MACOS_MONITOR (self), 0);
return self->screen_id;
}

View File

@ -0,0 +1,43 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_MONITOR_H__
#define __GDK_MACOS_MONITOR_H__
#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/macos/gdkmacos.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
typedef struct _GdkMacosMonitor GdkMacosMonitor;
typedef struct _GdkMacosMonitorClass GdkMacosMonitorClass;
#define GDK_TYPE_MACOS_MONITOR (gdk_macos_monitor_get_type())
#define GDK_MACOS_MONITOR(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_MONITOR, GdkMacosMonitor))
#define GDK_IS_MACOS_MONITOR(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_MONITOR))
GDK_AVAILABLE_IN_ALL
GType gdk_macos_monitor_get_type (void);
G_END_DECLS
#endif /* __GDK_MACOS_MONITOR_H__ */

View File

@ -0,0 +1,48 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_POPUP_SURFACE_PRIVATE_H__
#define __GDK_MACOS_POPUP_SURFACE_PRIVATE_H__
#include "gdkmacossurface-private.h"
G_BEGIN_DECLS
typedef struct _GdkMacosPopupSurface GdkMacosPopupSurface;
typedef struct _GdkMacosPopupSurfaceClass GdkMacosPopupSurfaceClass;
#define GDK_TYPE_MACOS_POPUP_SURFACE (_gdk_macos_popup_surface_get_type())
#define GDK_MACOS_POPUP_SURFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_POPUP_SURFACE, GdkMacosPopupSurface))
#define GDK_IS_MACOS_POPUP_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_POPUP_SURFACE))
GType _gdk_macos_popup_surface_get_type (void);
GdkMacosSurface *_gdk_macos_popup_surface_new (GdkMacosDisplay *display,
GdkSurface *parent,
GdkFrameClock *frame_clock,
int x,
int y,
int width,
int height);
void _gdk_macos_popup_surface_attach_to_parent (GdkMacosPopupSurface *self);
void _gdk_macos_popup_surface_detach_from_parent (GdkMacosPopupSurface *self);
void _gdk_macos_popup_surface_reposition (GdkMacosPopupSurface *self);
G_END_DECLS
#endif /* __GDK_MACOS_POPUP_SURFACE_PRIVATE_H__ */

View File

@ -0,0 +1,378 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#import "GdkMacosWindow.h"
#include "gdkinternals.h"
#include "gdkpopupprivate.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacospopupsurface-private.h"
#include "gdkmacosutils-private.h"
struct _GdkMacosPopupSurface
{
GdkMacosSurface parent_instance;
GdkPopupLayout *layout;
};
struct _GdkMacosPopupSurfaceClass
{
GdkMacosSurfaceClass parent_class;
};
static void
gdk_macos_popup_surface_layout (GdkMacosPopupSurface *self,
int width,
int height,
GdkPopupLayout *layout)
{
GdkRectangle final_rect;
int x, y;
g_assert (GDK_IS_MACOS_POPUP_SURFACE (self));
g_assert (layout != NULL);
g_assert (GDK_SURFACE (self)->parent);
if (layout != self->layout)
{
g_clear_pointer (&self->layout, gdk_popup_layout_unref);
self->layout = gdk_popup_layout_ref (layout);
}
gdk_surface_layout_popup_helper (GDK_SURFACE (self),
width,
height,
layout,
&final_rect);
gdk_surface_get_origin (GDK_SURFACE (self)->parent, &x, &y);
x += final_rect.x;
y += final_rect.y;
if (final_rect.width != GDK_SURFACE (self)->width ||
final_rect.height != GDK_SURFACE (self)->height)
_gdk_macos_surface_move_resize (GDK_MACOS_SURFACE (self),
x,
y,
final_rect.width,
final_rect.height);
else if (x != GDK_MACOS_SURFACE (self)->root_x ||
y != GDK_MACOS_SURFACE (self)->root_y)
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self), x, y);
else
return;
gdk_surface_invalidate_rect (GDK_SURFACE (self), NULL);
}
static void
show_popup (GdkMacosPopupSurface *self)
{
_gdk_macos_surface_show (GDK_MACOS_SURFACE (self));
}
static void
show_grabbing_popup (GdkSeat *seat,
GdkSurface *surface,
gpointer user_data)
{
show_popup (GDK_MACOS_POPUP_SURFACE (surface));
}
static gboolean
gdk_macos_popup_surface_present (GdkPopup *popup,
int width,
int height,
GdkPopupLayout *layout)
{
GdkMacosPopupSurface *self = (GdkMacosPopupSurface *)popup;
g_assert (GDK_IS_MACOS_POPUP_SURFACE (self));
gdk_macos_popup_surface_layout (self, width, height, layout);
GDK_MACOS_SURFACE (self)->did_initial_present = TRUE;
if (GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self)))
return TRUE;
if (GDK_SURFACE (self)->autohide)
{
GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (popup));
GdkSeat *seat = gdk_display_get_default_seat (display);
gdk_seat_grab (seat,
GDK_SURFACE (self),
GDK_SEAT_CAPABILITY_ALL,
TRUE,
NULL, NULL,
show_grabbing_popup,
NULL);
}
else
{
show_popup (GDK_MACOS_POPUP_SURFACE (self));
}
return GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self));
}
static GdkGravity
gdk_macos_popup_surface_get_surface_anchor (GdkPopup *popup)
{
return GDK_SURFACE (popup)->popup.surface_anchor;
}
static GdkGravity
gdk_macos_popup_surface_get_rect_anchor (GdkPopup *popup)
{
return GDK_SURFACE (popup)->popup.rect_anchor;
}
static int
gdk_macos_popup_surface_get_position_x (GdkPopup *popup)
{
return GDK_SURFACE (popup)->x;
}
static int
gdk_macos_popup_surface_get_position_y (GdkPopup *popup)
{
return GDK_SURFACE (popup)->y;
}
static void
popup_interface_init (GdkPopupInterface *iface)
{
iface->present = gdk_macos_popup_surface_present;
iface->get_surface_anchor = gdk_macos_popup_surface_get_surface_anchor;
iface->get_rect_anchor = gdk_macos_popup_surface_get_rect_anchor;
iface->get_position_x = gdk_macos_popup_surface_get_position_x;
iface->get_position_y = gdk_macos_popup_surface_get_position_y;
}
G_DEFINE_TYPE_WITH_CODE (GdkMacosPopupSurface, _gdk_macos_popup_surface, GDK_TYPE_MACOS_SURFACE,
G_IMPLEMENT_INTERFACE (GDK_TYPE_POPUP, popup_interface_init))
enum {
PROP_0,
LAST_PROP,
};
static void
_gdk_macos_popup_surface_finalize (GObject *object)
{
GdkMacosPopupSurface *self = (GdkMacosPopupSurface *)object;
g_clear_object (&GDK_SURFACE (self)->parent);
g_clear_pointer (&self->layout, gdk_popup_layout_unref);
G_OBJECT_CLASS (_gdk_macos_popup_surface_parent_class)->finalize (object);
}
static void
_gdk_macos_popup_surface_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkSurface *surface = GDK_SURFACE (object);
switch (prop_id)
{
case LAST_PROP + GDK_POPUP_PROP_PARENT:
g_value_set_object (value, surface->parent);
break;
case LAST_PROP + GDK_POPUP_PROP_AUTOHIDE:
g_value_set_boolean (value, surface->autohide);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
_gdk_macos_popup_surface_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GdkSurface *surface = GDK_SURFACE (object);
switch (prop_id)
{
case LAST_PROP + GDK_POPUP_PROP_PARENT:
surface->parent = g_value_dup_object (value);
if (surface->parent)
surface->parent->children = g_list_prepend (surface->parent->children, surface);
break;
case LAST_PROP + GDK_POPUP_PROP_AUTOHIDE:
surface->autohide = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
_gdk_macos_popup_surface_class_init (GdkMacosPopupSurfaceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = _gdk_macos_popup_surface_finalize;
object_class->get_property = _gdk_macos_popup_surface_get_property;
object_class->set_property = _gdk_macos_popup_surface_set_property;
gdk_popup_install_properties (object_class, 1);
}
static void
_gdk_macos_popup_surface_init (GdkMacosPopupSurface *self)
{
}
GdkMacosSurface *
_gdk_macos_popup_surface_new (GdkMacosDisplay *display,
GdkSurface *parent,
GdkFrameClock *frame_clock,
int x,
int y,
int width,
int height)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkMacosWindow *window;
GdkMacosSurface *self;
NSScreen *screen;
NSUInteger style_mask;
NSRect content_rect;
NSRect screen_rect;
int nx;
int ny;
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
g_return_val_if_fail (!frame_clock || GDK_IS_FRAME_CLOCK (frame_clock), NULL);
g_return_val_if_fail (!parent || GDK_IS_MACOS_SURFACE (parent), NULL);
style_mask = NSWindowStyleMaskBorderless;
_gdk_macos_display_to_display_coords (display, x, y, &nx, &ny);
screen = _gdk_macos_display_get_screen_at_display_coords (display, nx, ny);
screen_rect = [screen frame];
nx -= screen_rect.origin.x;
ny -= screen_rect.origin.y;
content_rect = NSMakeRect (nx, ny - height, width, height);
window = [[GdkMacosWindow alloc] initWithContentRect:content_rect
styleMask:style_mask
backing:NSBackingStoreBuffered
defer:NO
screen:screen];
[window setOpaque:NO];
[window setBackgroundColor:[NSColor clearColor]];
[window setDecorated:NO];
#if 0
/* NOTE: We could set these to be popup level, but then
* [NSApp orderedWindows] would not give us the windows
* back with the stacking order applied.
*/
[window setLevel:NSPopUpMenuWindowLevel];
#endif
self = g_object_new (GDK_TYPE_MACOS_POPUP_SURFACE,
"display", display,
"frame-clock", frame_clock,
"native", window,
"parent", parent,
NULL);
GDK_END_MACOS_ALLOC_POOL;
return g_steal_pointer (&self);
}
void
_gdk_macos_popup_surface_attach_to_parent (GdkMacosPopupSurface *self)
{
GdkSurface *surface = (GdkSurface *)self;
g_return_if_fail (GDK_IS_MACOS_POPUP_SURFACE (self));
if (GDK_SURFACE_DESTROYED (surface))
return;
if (surface->parent != NULL && !GDK_SURFACE_DESTROYED (surface->parent))
{
NSWindow *parent = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface->parent));
NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
[parent addChildWindow:window ordered:NSWindowAbove];
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
}
}
void
_gdk_macos_popup_surface_detach_from_parent (GdkMacosPopupSurface *self)
{
GdkSurface *surface = (GdkSurface *)self;
g_return_if_fail (GDK_IS_MACOS_POPUP_SURFACE (self));
if (GDK_SURFACE_DESTROYED (surface))
return;
if (surface->parent != NULL && !GDK_SURFACE_DESTROYED (surface->parent))
{
NSWindow *parent = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface->parent));
NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
[parent removeChildWindow:window];
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
}
}
void
_gdk_macos_popup_surface_reposition (GdkMacosPopupSurface *self)
{
g_return_if_fail (GDK_IS_MACOS_POPUP_SURFACE (self));
if (self->layout == NULL ||
!gdk_surface_get_mapped (GDK_SURFACE (self)) ||
GDK_SURFACE (self)->parent == NULL)
return;
gdk_macos_popup_surface_layout (self,
GDK_SURFACE (self)->width,
GDK_SURFACE (self)->height,
self->layout);
}

View File

@ -0,0 +1,35 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_SEAT_PRIVATE_H__
#define __GDK_MACOS_SEAT_PRIVATE_H__
#include <AppKit/AppKit.h>
#include "gdkmacosdisplay.h"
#include "gdkseatprivate.h"
G_BEGIN_DECLS
GdkSeat *_gdk_macos_seat_new (GdkMacosDisplay *display);
G_END_DECLS
#endif /* __GDK_MACOS_SEAT_PRIVATE_H__ */

65
gdk/macos/gdkmacosseat.c Normal file
View File

@ -0,0 +1,65 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#include <gdk/gdk.h>
#include "gdkdeviceprivate.h"
#include "gdkseatdefaultprivate.h"
#include "gdkmacosdevice.h"
#include "gdkmacosseat-private.h"
GdkSeat *
_gdk_macos_seat_new (GdkMacosDisplay *display)
{
GdkDevice *core_keyboard;
GdkDevice *core_pointer;
GdkSeat *seat;
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
core_pointer = g_object_new (GDK_TYPE_MACOS_DEVICE,
"name", "Core Pointer",
"type", GDK_DEVICE_TYPE_LOGICAL,
"source", GDK_SOURCE_MOUSE,
"has-cursor", TRUE,
"display", display,
NULL);
core_keyboard = g_object_new (GDK_TYPE_MACOS_DEVICE,
"name", "Core Keyboard",
"type", GDK_DEVICE_TYPE_LOGICAL,
"source", GDK_SOURCE_KEYBOARD,
"has-cursor", FALSE,
"display", display,
NULL);
_gdk_device_set_associated_device (GDK_DEVICE (core_pointer),
GDK_DEVICE (core_keyboard));
_gdk_device_set_associated_device (GDK_DEVICE (core_keyboard),
GDK_DEVICE (core_pointer));
seat = gdk_seat_default_new_for_logical_pair (core_pointer, core_keyboard);
g_object_unref (core_pointer);
g_object_unref (core_keyboard);
return g_steal_pointer (&seat);
}

View File

@ -0,0 +1,131 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_SURFACE_PRIVATE_H__
#define __GDK_MACOS_SURFACE_PRIVATE_H__
#include <AppKit/AppKit.h>
#include <cairo.h>
#include "gdkinternals.h"
#include "gdksurfaceprivate.h"
#include "gdkmacosdisplay.h"
#include "gdkmacossurface.h"
#import "GdkMacosWindow.h"
G_BEGIN_DECLS
#define GDK_MACOS_SURFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_MACOS_SURFACE, GdkMacosSurfaceClass))
#define GDK_IS_MACOS_SURFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_MACOS_SURFACE))
#define GDK_MACOS_SURFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_MACOS_SURFACE, GdkMacosSurfaceClass))
struct _GdkMacosSurface
{
GdkSurface parent_instance;
GList main;
GList sorted;
GList frame;
GdkMacosWindow *window;
GPtrArray *monitors;
cairo_region_t *input_region;
char *title;
int root_x;
int root_y;
int shadow_top;
int shadow_right;
int shadow_bottom;
int shadow_left;
gint64 pending_frame_counter;
guint did_initial_present : 1;
};
struct _GdkMacosSurfaceClass
{
GdkSurfaceClass parent_class;
};
GdkMacosSurface *_gdk_macos_surface_new (GdkMacosDisplay *display,
GdkSurfaceType surface_type,
GdkSurface *parent,
int x,
int y,
int width,
int height);
NSWindow *_gdk_macos_surface_get_native (GdkMacosSurface *self);
CGDirectDisplayID _gdk_macos_surface_get_screen_id (GdkMacosSurface *self);
const char *_gdk_macos_surface_get_title (GdkMacosSurface *self);
void _gdk_macos_surface_set_title (GdkMacosSurface *self,
const gchar *title);
void _gdk_macos_surface_get_shadow (GdkMacosSurface *self,
gint *top,
gint *right,
gint *bottom,
gint *left);
NSView *_gdk_macos_surface_get_view (GdkMacosSurface *self);
gboolean _gdk_macos_surface_get_modal_hint (GdkMacosSurface *self);
void _gdk_macos_surface_set_modal_hint (GdkMacosSurface *self,
gboolean modal_hint);
void _gdk_macos_surface_set_geometry_hints (GdkMacosSurface *self,
const GdkGeometry *geometry,
GdkSurfaceHints geom_mask);
void _gdk_macos_surface_resize (GdkMacosSurface *self,
int width,
int height);
void _gdk_macos_surface_update_fullscreen_state (GdkMacosSurface *self);
void _gdk_macos_surface_update_position (GdkMacosSurface *self);
void _gdk_macos_surface_show (GdkMacosSurface *self);
void _gdk_macos_surface_thaw (GdkMacosSurface *self,
gint64 predicted_presentation_time,
gint64 refresh_interval);
CGContextRef _gdk_macos_surface_acquire_context (GdkMacosSurface *self,
gboolean clear_scale,
gboolean antialias);
void _gdk_macos_surface_release_context (GdkMacosSurface *self,
CGContextRef cg_context);
void _gdk_macos_surface_synthesize_null_key (GdkMacosSurface *self);
void _gdk_macos_surface_move (GdkMacosSurface *self,
int x,
int y);
void _gdk_macos_surface_move_resize (GdkMacosSurface *self,
int x,
int y,
int width,
int height);
gboolean _gdk_macos_surface_is_tracking (GdkMacosSurface *self,
NSTrackingArea *area);
void _gdk_macos_surface_monitor_changed (GdkMacosSurface *self);
GdkMonitor *_gdk_macos_surface_get_best_monitor (GdkMacosSurface *self);
void _gdk_macos_surface_reposition_children (GdkMacosSurface *self);
void _gdk_macos_surface_set_opacity (GdkMacosSurface *self,
double opacity);
void _gdk_macos_surface_get_root_coords (GdkMacosSurface *self,
int *x,
int *y);
G_END_DECLS
#endif /* __GDK_MACOS_SURFACE_PRIVATE_H__ */

1071
gdk/macos/gdkmacossurface.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,43 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_SURFACE_H__
#define __GDK_MACOS_SURFACE_H__
#if !defined (__GDKMACOS_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/macos/gdkmacos.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
typedef struct _GdkMacosSurface GdkMacosSurface;
typedef struct _GdkMacosSurfaceClass GdkMacosSurfaceClass;
#define GDK_TYPE_MACOS_SURFACE (gdk_macos_surface_get_type())
#define GDK_MACOS_SURFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_SURFACE, GdkMacosSurface))
#define GDK_IS_MACOS_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_SURFACE))
GDK_AVAILABLE_IN_ALL
GType gdk_macos_surface_get_type (void);
G_END_DECLS
#endif /* __GDK_MACOS_SURFACE_H__ */

View File

@ -0,0 +1,47 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_TOPLEVEL_SURFACE_PRIVATE_H__
#define __GDK_MACOS_TOPLEVEL_SURFACE_PRIVATE_H__
#include "gdkmacossurface-private.h"
G_BEGIN_DECLS
typedef struct _GdkMacosToplevelSurface GdkMacosToplevelSurface;
typedef struct _GdkMacosToplevelSurfaceClass GdkMacosToplevelSurfaceClass;
#define GDK_TYPE_MACOS_TOPLEVEL_SURFACE (_gdk_macos_toplevel_surface_get_type())
#define GDK_MACOS_TOPLEVEL_SURFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_TOPLEVEL_SURFACE, GdkMacosToplevelSurface))
#define GDK_IS_MACOS_TOPLEVEL_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_TOPLEVEL_SURFACE))
GType _gdk_macos_toplevel_surface_get_type (void);
GdkMacosSurface *_gdk_macos_toplevel_surface_new (GdkMacosDisplay *display,
GdkSurface *parent,
GdkFrameClock *frame_clock,
int x,
int y,
int width,
int height);
void _gdk_macos_toplevel_surface_attach_to_parent (GdkMacosToplevelSurface *self);
void _gdk_macos_toplevel_surface_detach_from_parent (GdkMacosToplevelSurface *self);
G_END_DECLS
#endif /* __GDK_MACOS_TOPLEVEL_SURFACE_PRIVATE_H__ */

View File

@ -0,0 +1,581 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#include "config.h"
#import "GdkMacosWindow.h"
#include "gdkinternals.h"
#include "gdktoplevelprivate.h"
#include "gdkmacosdisplay-private.h"
#include "gdkmacostoplevelsurface-private.h"
#include "gdkmacosutils-private.h"
struct _GdkMacosToplevelSurface
{
GdkMacosSurface parent_instance;
guint decorated : 1;
};
struct _GdkMacosToplevelSurfaceClass
{
GdkMacosSurfaceClass parent_instance;
};
static void
_gdk_macos_toplevel_surface_fullscreen (GdkMacosToplevelSurface *self)
{
NSWindow *window;
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
if (([window styleMask] & NSWindowStyleMaskFullScreen) == 0)
[window toggleFullScreen:window];
}
static void
_gdk_macos_toplevel_surface_unfullscreen (GdkMacosToplevelSurface *self)
{
NSWindow *window;
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
if (([window styleMask] & NSWindowStyleMaskFullScreen) != 0)
[window toggleFullScreen:window];
}
static void
_gdk_macos_toplevel_surface_maximize (GdkMacosToplevelSurface *self)
{
NSWindow *window;
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
if (![window isZoomed])
[window zoom:window];
}
static void
_gdk_macos_toplevel_surface_unmaximize (GdkMacosToplevelSurface *self)
{
NSWindow *window;
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
if ([window isZoomed])
[window zoom:window];
}
static gboolean
_gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
int width,
int height,
GdkToplevelLayout *layout)
{
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
NSWindow *nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
GdkGeometry geometry;
GdkSurfaceHints mask;
NSWindowStyleMask style_mask;
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
g_assert (GDK_IS_MACOS_WINDOW (nswindow));
style_mask = [nswindow styleMask];
if (gdk_toplevel_layout_get_resizable (layout))
{
geometry.min_width = gdk_toplevel_layout_get_min_width (layout);
geometry.min_height = gdk_toplevel_layout_get_min_height (layout);
mask = GDK_HINT_MIN_SIZE;
/* Only set 'Resizable' mask to get native resize zones if the window is
* titled, otherwise we do this internally for CSD and do not need
* NSWindow to do it for us. Additionally, it can mess things up when
* doing a window resize since it can cause mouseDown to get passed
* through to the next window.
*/
if ((style_mask & NSWindowStyleMaskTitled) != 0)
style_mask |= NSWindowStyleMaskResizable;
else
style_mask &= ~NSWindowStyleMaskResizable;
}
else
{
geometry.max_width = geometry.min_width = width;
geometry.max_height = geometry.min_height = height;
mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
style_mask &= ~NSWindowStyleMaskResizable;
}
if (style_mask != [nswindow styleMask])
[nswindow setStyleMask:style_mask];
_gdk_macos_surface_set_geometry_hints (GDK_MACOS_SURFACE (self), &geometry, mask);
gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
_gdk_macos_surface_resize (GDK_MACOS_SURFACE (self), width, height);
/* Maximized state */
if (gdk_toplevel_layout_get_maximized (layout))
_gdk_macos_toplevel_surface_maximize (self);
else
_gdk_macos_toplevel_surface_unmaximize (self);
/* Fullscreen state */
if (gdk_toplevel_layout_get_fullscreen (layout))
_gdk_macos_toplevel_surface_fullscreen (self);
else
_gdk_macos_toplevel_surface_unfullscreen (self);
if (GDK_SURFACE (self)->transient_for != NULL)
{
}
else
{
if (!self->decorated &&
!GDK_MACOS_SURFACE (self)->did_initial_present &&
GDK_SURFACE (self)->x == 0 &&
GDK_SURFACE (self)->y == 0 &&
(GDK_MACOS_SURFACE (self)->shadow_left ||
GDK_MACOS_SURFACE (self)->shadow_top))
{
GdkMonitor *monitor = _gdk_macos_surface_get_best_monitor (GDK_MACOS_SURFACE (self));
int x = GDK_SURFACE (self)->x;
int y = GDK_SURFACE (self)->y;
if (monitor != NULL)
{
GdkRectangle visible;
gdk_monitor_get_workarea (monitor, &visible);
if (x < visible.x)
x = visible.x;
if (y < visible.y)
y = visible.y;
}
x -= GDK_MACOS_SURFACE (self)->shadow_left;
y -= GDK_MACOS_SURFACE (self)->shadow_top;
_gdk_macos_surface_move (GDK_MACOS_SURFACE (self), x, y);
}
}
_gdk_macos_surface_show (GDK_MACOS_SURFACE (self));
GDK_MACOS_SURFACE (self)->did_initial_present = TRUE;
return TRUE;
}
static gboolean
_gdk_macos_toplevel_surface_minimize (GdkToplevel *toplevel)
{
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
[window miniaturize:window];
return TRUE;
}
static gboolean
_gdk_macos_toplevel_surface_lower (GdkToplevel *toplevel)
{
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
[window orderBack:window];
return TRUE;
}
static void
_gdk_macos_toplevel_surface_focus (GdkToplevel *toplevel,
guint32 timestamp)
{
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
NSWindow *nswindow;
if (GDK_SURFACE_DESTROYED (self))
return;
nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
[nswindow makeKeyAndOrderFront:nswindow];
}
static void
_gdk_macos_toplevel_surface_begin_resize (GdkToplevel *toplevel,
GdkSurfaceEdge edge,
GdkDevice *device,
int button,
double root_x,
double root_y,
guint32 timestamp)
{
NSWindow *nswindow;
g_assert (GDK_IS_MACOS_SURFACE (toplevel));
if (GDK_SURFACE_DESTROYED (toplevel))
return;
/* Release passive grab */
if (button != 0)
gdk_seat_ungrab (gdk_device_get_seat (device));
if ((nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (toplevel))))
[(GdkMacosWindow *)nswindow beginManualResize:edge];
}
static void
_gdk_macos_toplevel_surface_begin_move (GdkToplevel *toplevel,
GdkDevice *device,
int button,
double root_x,
double root_y,
guint32 timestamp)
{
NSWindow *nswindow;
g_assert (GDK_IS_MACOS_SURFACE (toplevel));
if (GDK_SURFACE_DESTROYED (toplevel))
return;
/* Release passive grab */
if (button != 0)
gdk_seat_ungrab (gdk_device_get_seat (device));
if ((nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (toplevel))))
[(GdkMacosWindow *)nswindow beginManualMove];
}
static void
toplevel_iface_init (GdkToplevelInterface *iface)
{
iface->present = _gdk_macos_toplevel_surface_present;
iface->minimize = _gdk_macos_toplevel_surface_minimize;
iface->lower = _gdk_macos_toplevel_surface_lower;
iface->focus = _gdk_macos_toplevel_surface_focus;
iface->begin_resize = _gdk_macos_toplevel_surface_begin_resize;
iface->begin_move = _gdk_macos_toplevel_surface_begin_move;
}
G_DEFINE_TYPE_WITH_CODE (GdkMacosToplevelSurface, _gdk_macos_toplevel_surface, GDK_TYPE_MACOS_SURFACE,
G_IMPLEMENT_INTERFACE (GDK_TYPE_TOPLEVEL, toplevel_iface_init))
enum {
PROP_0,
LAST_PROP
};
static void
_gdk_macos_toplevel_surface_set_transient_for (GdkMacosToplevelSurface *self,
GdkMacosSurface *parent)
{
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
g_assert (!parent || GDK_IS_MACOS_SURFACE (parent));
_gdk_macos_toplevel_surface_detach_from_parent (self);
g_clear_object (&GDK_SURFACE (self)->transient_for);
if (g_set_object (&GDK_SURFACE (self)->transient_for, GDK_SURFACE (parent)))
_gdk_macos_toplevel_surface_attach_to_parent (self);
}
static void
_gdk_macos_toplevel_surface_set_decorated (GdkMacosToplevelSurface *self,
gboolean decorated)
{
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
decorated = !!decorated;
if (decorated != self->decorated)
{
NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
self->decorated = decorated;
[(GdkMacosWindow *)window setDecorated:(BOOL)decorated];
}
}
static void
_gdk_macos_toplevel_surface_hide (GdkSurface *surface)
{
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)surface;
_gdk_macos_toplevel_surface_detach_from_parent (self);
GDK_SURFACE_CLASS (_gdk_macos_toplevel_surface_parent_class)->hide (surface);
}
static void
_gdk_macos_toplevel_surface_destroy (GdkSurface *surface,
gboolean foreign_destroy)
{
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)surface;
g_clear_object (&GDK_SURFACE (self)->transient_for);
GDK_SURFACE_CLASS (_gdk_macos_toplevel_surface_parent_class)->destroy (surface, foreign_destroy);
}
static void
_gdk_macos_toplevel_surface_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdkSurface *surface = GDK_SURFACE (object);
GdkMacosSurface *base = GDK_MACOS_SURFACE (surface);
GdkMacosToplevelSurface *toplevel = GDK_MACOS_TOPLEVEL_SURFACE (base);
switch (prop_id)
{
case LAST_PROP + GDK_TOPLEVEL_PROP_STATE:
g_value_set_flags (value, surface->state);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_TITLE:
g_value_set_string (value, _gdk_macos_surface_get_title (base));
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_STARTUP_ID:
g_value_set_string (value, "");
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_TRANSIENT_FOR:
g_value_set_object (value, GDK_SURFACE (toplevel)->transient_for);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_MODAL:
g_value_set_boolean (value, GDK_SURFACE (toplevel)->modal_hint);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST:
g_value_set_pointer (value, NULL);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_DECORATED:
g_value_set_boolean (value, toplevel->decorated);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE:
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_FULLSCREEN_MODE:
g_value_set_enum (value, surface->fullscreen_mode);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED:
g_value_set_boolean (value, surface->shortcuts_inhibited);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
_gdk_macos_toplevel_surface_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GdkSurface *surface = GDK_SURFACE (object);
GdkMacosSurface *base = GDK_MACOS_SURFACE (surface);
GdkMacosToplevelSurface *toplevel = GDK_MACOS_TOPLEVEL_SURFACE (base);
switch (prop_id)
{
case LAST_PROP + GDK_TOPLEVEL_PROP_TITLE:
_gdk_macos_surface_set_title (base, g_value_get_string (value));
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_STARTUP_ID:
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_TRANSIENT_FOR:
_gdk_macos_toplevel_surface_set_transient_for (toplevel, g_value_get_object (value));
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_MODAL:
GDK_SURFACE (surface)->modal_hint = g_value_get_boolean (value);
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST:
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_DECORATED:
_gdk_macos_toplevel_surface_set_decorated (toplevel, g_value_get_boolean (value));
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE:
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_FULLSCREEN_MODE:
surface->fullscreen_mode = g_value_get_enum (value);
g_object_notify_by_pspec (G_OBJECT (surface), pspec);
break;
case LAST_PROP + GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED:
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
_gdk_macos_toplevel_surface_class_init (GdkMacosToplevelSurfaceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkSurfaceClass *surface_class = GDK_SURFACE_CLASS (klass);
object_class->get_property = _gdk_macos_toplevel_surface_get_property;
object_class->set_property = _gdk_macos_toplevel_surface_set_property;
surface_class->destroy = _gdk_macos_toplevel_surface_destroy;
surface_class->hide = _gdk_macos_toplevel_surface_hide;
gdk_toplevel_install_properties (object_class, LAST_PROP);
}
static void
_gdk_macos_toplevel_surface_init (GdkMacosToplevelSurface *self)
{
self->decorated = TRUE;
}
GdkMacosSurface *
_gdk_macos_toplevel_surface_new (GdkMacosDisplay *display,
GdkSurface *parent,
GdkFrameClock *frame_clock,
int x,
int y,
int width,
int height)
{
GDK_BEGIN_MACOS_ALLOC_POOL;
GdkMacosWindow *window;
GdkMacosSurface *self;
NSScreen *screen;
NSUInteger style_mask;
NSRect content_rect;
NSRect screen_rect;
int nx;
int ny;
g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (display), NULL);
g_return_val_if_fail (!frame_clock || GDK_IS_FRAME_CLOCK (frame_clock), NULL);
g_return_val_if_fail (!parent || GDK_IS_MACOS_SURFACE (parent), NULL);
style_mask = (NSWindowStyleMaskTitled |
NSWindowStyleMaskClosable |
NSWindowStyleMaskMiniaturizable |
NSWindowStyleMaskResizable);
_gdk_macos_display_to_display_coords (display, x, y, &nx, &ny);
screen = _gdk_macos_display_get_screen_at_display_coords (display, nx, ny);
screen_rect = [screen visibleFrame];
nx -= screen_rect.origin.x;
ny -= screen_rect.origin.y;
content_rect = NSMakeRect (nx, ny - height, width, height);
window = [[GdkMacosWindow alloc] initWithContentRect:content_rect
styleMask:style_mask
backing:NSBackingStoreBuffered
defer:NO
screen:screen];
self = g_object_new (GDK_TYPE_MACOS_TOPLEVEL_SURFACE,
"display", display,
"frame-clock", frame_clock,
"native", window,
NULL);
GDK_END_MACOS_ALLOC_POOL;
return g_steal_pointer (&self);
}
void
_gdk_macos_toplevel_surface_attach_to_parent (GdkMacosToplevelSurface *self)
{
GdkSurface *surface = (GdkSurface *)self;
g_return_if_fail (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
if (GDK_SURFACE_DESTROYED (surface))
return;
if (surface->transient_for != NULL &&
!GDK_SURFACE_DESTROYED (surface->transient_for))
{
NSWindow *parent = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface->transient_for));
NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
[parent addChildWindow:window ordered:NSWindowAbove];
if (GDK_SURFACE (self)->modal_hint)
[window setLevel:NSModalPanelWindowLevel];
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
}
}
void
_gdk_macos_toplevel_surface_detach_from_parent (GdkMacosToplevelSurface *self)
{
GdkSurface *surface = (GdkSurface *)self;
g_return_if_fail (GDK_IS_MACOS_TOPLEVEL_SURFACE (self));
if (GDK_SURFACE_DESTROYED (surface))
return;
if (surface->transient_for != NULL &&
!GDK_SURFACE_DESTROYED (surface->transient_for))
{
NSWindow *parent = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (surface->transient_for));
NSWindow *window = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
[parent removeChildWindow:window];
[window setLevel:NSNormalWindowLevel];
_gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (surface->display));
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright © 2020 Red Hat, Inc.
*
* 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.1 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/>.
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*/
#ifndef __GDK_MACOS_UTILS_PRIVATE_H__
#define __GDK_MACOS_UTILS_PRIVATE_H__
#include <AppKit/AppKit.h>
#include <gdk/gdk.h>
#define GDK_BEGIN_MACOS_ALLOC_POOL NSAutoreleasePool *_pool = [[NSAutoreleasePool alloc] init]
#define GDK_END_MACOS_ALLOC_POOL [_pool release]
static inline gboolean
queue_contains (GQueue *queue,
GList *link_)
{
return queue->head == link_ || link_->prev || link_->next;
}
#endif /* __GDK_MACOS_UTILS_PRIVATE_H__ */

62
gdk/macos/meson.build Normal file
View File

@ -0,0 +1,62 @@
gdk_macos_sources = files([
'edgesnapping.c',
'gdkdisplaylinksource.c',
'gdkmacoscairocontext.c',
'gdkmacosclipboard.c',
'gdkmacoscursor.c',
'gdkmacosdevice.c',
'gdkmacosdisplay.c',
'gdkmacosdisplay-settings.c',
'gdkmacosdisplay-translate.c',
'gdkmacosdrag.c',
'gdkmacosdragsurface.c',
'gdkmacosglcontext.c',
'gdkmacoseventsource.c',
'gdkmacoskeymap.c',
'gdkmacosmonitor.c',
'gdkmacospopupsurface.c',
'gdkmacosseat.c',
'gdkmacossurface.c',
'gdkmacostoplevelsurface.c',
'GdkMacosBaseView.c',
'GdkMacosCairoView.c',
'GdkMacosCairoSubview.c',
'GdkMacosGLLayer.c',
'GdkMacosWindow.c',
])
gdk_macos_public_headers = files([
'gdkmacosdevice.h',
'gdkmacosdisplay.h',
'gdkmacosglcontext.h',
'gdkmacoskeymap.h',
'gdkmacosmonitor.h',
'gdkmacossurface.h',
])
install_headers(gdk_macos_public_headers, 'gdkmacos.h', subdir: 'gtk-4.0/gdk/macos/')
gdk_macos_frameworks = [
'AppKit',
'Carbon',
'CoreVideo',
'CoreServices',
'OpenGL',
'QuartzCore',
]
gdk_macos_deps = [
dependency('appleframeworks', modules: gdk_macos_frameworks)
]
libgdk_c_args += ['-xobjective-c']
libgdk_macos = static_library('gdk-macos',
gdk_macos_sources, gdkconfig, gdkenum_h,
include_directories: [ confinc, gdkinc, ],
c_args: libgdk_c_args + common_cflags,
link_args: common_ldflags,
link_with: [],
dependencies: gdk_deps + gdk_macos_deps)

View File

@ -143,6 +143,7 @@ gdkconfig_cdata.set('GDK_WINDOWING_X11', x11_enabled)
gdkconfig_cdata.set('GDK_WINDOWING_WAYLAND', wayland_enabled)
gdkconfig_cdata.set('GDK_WINDOWING_WIN32', win32_enabled)
gdkconfig_cdata.set('GDK_WINDOWING_BROADWAY', broadway_enabled)
gdkconfig_cdata.set('GDK_WINDOWING_MACOS', macos_enabled)
gdkconfig_cdata.set('GDK_RENDERING_VULKAN', have_vulkan)
gdkconfig = configure_file(
@ -216,9 +217,14 @@ if wayland_enabled or broadway_enabled
endif
endif
libgdk_c_args = [
'-DGTK_COMPILATION',
'-DG_LOG_DOMAIN="Gdk"',
]
gdk_backends = []
gdk_backends_gen_headers = [] # non-public generated headers
foreach backend : ['broadway', 'quartz', 'wayland', 'win32', 'x11']
foreach backend : ['broadway', 'quartz', 'wayland', 'win32', 'x11', 'macos']
if get_variable('@0@_enabled'.format(backend))
subdir(backend)
gdk_deps += get_variable('gdk_@0@_deps'.format(backend))
@ -235,16 +241,12 @@ if gdk_backends.length() == 0
error('No backends enabled')
endif
# FIXME: might have to add '-xobjective-c' to c_args for quartz backend?
libgdk = static_library('gdk',
sources: [gdk_sources, gdk_backends_gen_headers, gdkconfig],
dependencies: gdk_deps + [libgtk_css_dep],
link_with: [libgtk_css, ],
include_directories: [confinc, gdkx11_inc, wlinc],
c_args: [
'-DGTK_COMPILATION',
'-DG_LOG_DOMAIN="Gdk"',
] + common_cflags,
c_args: libgdk_c_args + common_cflags,
link_whole: gdk_backends,
link_args: common_ldflags)

View File

@ -1,845 +0,0 @@
/* GdkQuartzSurface.m
*
* Copyright (C) 2005-2007 Imendio AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#import "GdkQuartzNSWindow.h"
#include "gdkquartzsurface.h"
#include "gdkdnd-quartz.h"
#include "gdkprivate-quartz.h"
@implementation GdkQuartzNSWindow
- (void)windowWillClose:(NSNotification*)notification
{
// Clears the delegate when window is going to be closed; since EL
// Capitan it is possible that the methods of delegate would get
// called after the window has been closed.
[self setDelegate:nil];
}
-(BOOL)windowShouldClose:(id)sender
{
GdkSurface *window = [[self contentView] gdkSurface];
GdkEvent *event;
event = gdk_event_new (GDK_DELETE);
event->any.surface = g_object_ref (window);
event->any.send_event = FALSE;
_gdk_event_queue_append (gdk_display_get_default (), event);
return NO;
}
-(void)windowWillMiniaturize:(NSNotification *)aNotification
{
GdkSurface *window = [[self contentView] gdkSurface];
_gdk_quartz_surface_detach_from_parent (window);
}
-(void)windowDidMiniaturize:(NSNotification *)aNotification
{
GdkSurface *window = [[self contentView] gdkSurface];
gdk_synthesize_surface_state (window, 0, GDK_SURFACE_STATE_MINIMIZED);
}
-(void)windowDidDeminiaturize:(NSNotification *)aNotification
{
GdkSurface *window = [[self contentView] gdkSurface];
_gdk_quartz_surface_attach_to_parent (window);
gdk_synthesize_surface_state (window, GDK_SURFACE_STATE_MINIMIZED, 0);
}
-(void)windowDidBecomeKey:(NSNotification *)aNotification
{
GdkSurface *window = [[self contentView] gdkSurface];
gdk_synthesize_surface_state (window, 0, GDK_SURFACE_STATE_FOCUSED);
_gdk_quartz_events_update_focus_window (window, TRUE);
}
-(void)windowDidResignKey:(NSNotification *)aNotification
{
GdkSurface *window = [[self contentView] gdkSurface];
_gdk_quartz_events_update_focus_window (window, FALSE);
gdk_synthesize_surface_state (window, GDK_SURFACE_STATE_FOCUSED, 0);
}
-(void)windowDidBecomeMain:(NSNotification *)aNotification
{
GdkSurface *window = [[self contentView] gdkSurface];
if (![self isVisible])
{
/* Note: This is a hack needed because for unknown reasons, hidden
* windows get shown when clicking the dock icon when the application
* is not already active.
*/
[self orderOut:nil];
return;
}
_gdk_quartz_surface_did_become_main (window);
}
-(void)windowDidResignMain:(NSNotification *)aNotification
{
GdkSurface *window;
window = [[self contentView] gdkSurface];
_gdk_quartz_surface_did_resign_main (window);
}
/* Used in combination with NSLeftMouseUp in sendEvent to keep track
* of when the window is being moved with the mouse.
*/
-(void)windowWillMove:(NSNotification *)aNotification
{
inMove = YES;
}
-(void)sendEvent:(NSEvent *)event
{
switch ([event type])
{
case NSLeftMouseUp:
{
double time = ((double)[event timestamp]) * 1000.0;
_gdk_quartz_events_break_all_grabs (time);
inManualMove = NO;
inManualResize = NO;
inMove = NO;
break;
}
case NSLeftMouseDragged:
if ([self trackManualMove] || [self trackManualResize])
return;
break;
default:
break;
}
[super sendEvent:event];
}
-(BOOL)isInMove
{
return inMove;
}
-(void)checkSendEnterNotify
{
GdkSurface *window = [[self contentView] gdkSurface];
GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
/* When a new window has been created, and the mouse
* is in the window area, we will not receive an NSMouseEntered
* event. Therefore, we synthesize an enter notify event manually.
*/
if (!initialPositionKnown)
{
initialPositionKnown = YES;
if (NSPointInRect ([NSEvent mouseLocation], [self frame]))
{
NSEvent *event;
event = [NSEvent enterExitEventWithType: NSMouseEntered
location: [self mouseLocationOutsideOfEventStream]
modifierFlags: 0
timestamp: [[NSApp currentEvent] timestamp]
windowNumber: [impl->toplevel windowNumber]
context: NULL
eventNumber: 0
trackingNumber: [impl->view trackingRect]
userData: nil];
[NSApp postEvent:event atStart:NO];
}
}
}
-(void)windowDidMove:(NSNotification *)aNotification
{
GdkSurface *window = [[self contentView] gdkSurface];
GdkEvent *event;
GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
gboolean maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
/* In case the window is changed when maximized remove the maximized state */
if (maximized && !inMaximizeTransition && !NSEqualRects (lastMaximizedFrame, [self frame]))
{
gdk_synthesize_surface_state (window,
GDK_SURFACE_STATE_MAXIMIZED,
0);
}
_gdk_quartz_surface_update_position (window);
/* Synthesize a configure event */
event = gdk_event_new (GDK_CONFIGURE);
event->configure.window = g_object_ref (window);
event->configure.x = window->x;
event->configure.y = window->y;
event->configure.width = window->width;
event->configure.height = window->height;
_gdk_event_queue_append (gdk_display_get_default (), event);
[self checkSendEnterNotify];
}
-(void)windowDidResize:(NSNotification *)aNotification
{
NSRect content_rect = [self contentRectForFrameRect:[self frame]];
GdkSurface *window = [[self contentView] gdkSurface];
GdkEvent *event;
GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
gboolean maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
/* see same in windowDidMove */
if (maximized && !inMaximizeTransition && !NSEqualRects (lastMaximizedFrame, [self frame]))
{
gdk_synthesize_surface_state (window,
GDK_SURFACE_STATE_MAXIMIZED,
0);
}
window->width = content_rect.size.width;
window->height = content_rect.size.height;
/* Certain resize operations (e.g. going fullscreen), also move the
* origin of the window.
*/
_gdk_quartz_surface_update_position (window);
[[self contentView] setFrame:NSMakeRect (0, 0, window->width, window->height)];
_gdk_surface_update_size (window);
/* Synthesize a configure event */
event = gdk_event_new (GDK_CONFIGURE);
event->configure.window = g_object_ref (window);
event->configure.x = window->x;
event->configure.y = window->y;
event->configure.width = window->width;
event->configure.height = window->height;
_gdk_event_queue_append (gdk_display_get_default (), event);
[self checkSendEnterNotify];
}
-(id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask backing:(NSBackingStoreType)backingType defer:(BOOL)flag screen:(NSScreen *)screen
{
self = [super initWithContentRect:contentRect
styleMask:styleMask
backing:backingType
defer:flag
screen:screen];
[self setAcceptsMouseMovedEvents:YES];
[self setDelegate:self];
[self setReleasedWhenClosed:YES];
return self;
}
-(BOOL)canBecomeMainWindow
{
GdkSurface *window = [[self contentView] gdkSurface];
GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
switch (impl->type_hint)
{
case GDK_SURFACE_TYPE_HINT_NORMAL:
case GDK_SURFACE_TYPE_HINT_DIALOG:
return YES;
case GDK_SURFACE_TYPE_HINT_MENU:
case GDK_SURFACE_TYPE_HINT_TOOLBAR:
case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
case GDK_SURFACE_TYPE_HINT_UTILITY:
case GDK_SURFACE_TYPE_HINT_DOCK:
case GDK_SURFACE_TYPE_HINT_DESKTOP:
case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU:
case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
case GDK_SURFACE_TYPE_HINT_TOOLTIP:
case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
case GDK_SURFACE_TYPE_HINT_COMBO:
case GDK_SURFACE_TYPE_HINT_DND:
return NO;
}
return YES;
}
-(BOOL)canBecomeKeyWindow
{
GdkSurface *window = [[self contentView] gdkSurface];
GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
if (!window->accept_focus)
return NO;
/* Popup windows should not be able to get focused in the window
* manager sense, it's only handled through grabs.
*/
if (window->surface_type == GDK_SURFACE_TEMP)
return NO;
switch (impl->type_hint)
{
case GDK_SURFACE_TYPE_HINT_NORMAL:
case GDK_SURFACE_TYPE_HINT_DIALOG:
case GDK_SURFACE_TYPE_HINT_MENU:
case GDK_SURFACE_TYPE_HINT_TOOLBAR:
case GDK_SURFACE_TYPE_HINT_UTILITY:
case GDK_SURFACE_TYPE_HINT_DOCK:
case GDK_SURFACE_TYPE_HINT_DESKTOP:
case GDK_SURFACE_TYPE_HINT_DROPDOWN_MENU:
case GDK_SURFACE_TYPE_HINT_POPUP_MENU:
case GDK_SURFACE_TYPE_HINT_COMBO:
return YES;
case GDK_SURFACE_TYPE_HINT_SPLASHSCREEN:
case GDK_SURFACE_TYPE_HINT_TOOLTIP:
case GDK_SURFACE_TYPE_HINT_NOTIFICATION:
case GDK_SURFACE_TYPE_HINT_DND:
return NO;
}
return YES;
}
- (void)showAndMakeKey:(BOOL)makeKey
{
GdkSurface *window = [[self contentView] gdkSurface];
GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
inShowOrHide = YES;
if (makeKey)
[impl->toplevel makeKeyAndOrderFront:impl->toplevel];
else
[impl->toplevel orderFront:nil];
inShowOrHide = NO;
[self checkSendEnterNotify];
}
- (void)hide
{
GdkSurface *window = [[self contentView] gdkSurface];
GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
inShowOrHide = YES;
[impl->toplevel orderOut:nil];
inShowOrHide = NO;
initialPositionKnown = NO;
}
- (BOOL)trackManualMove
{
GdkSurface *window = [[self contentView] gdkSurface];
GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
NSPoint currentLocation;
NSPoint newOrigin;
NSRect screenFrame = [[NSScreen mainScreen] visibleFrame];
NSRect windowFrame = [self frame];
if (!inManualMove)
return NO;
currentLocation = [self convertBaseToScreen:[self mouseLocationOutsideOfEventStream]];
newOrigin.x = currentLocation.x - initialMoveLocation.x;
newOrigin.y = currentLocation.y - initialMoveLocation.y;
/* Clamp vertical position to below the menu bar. */
if (newOrigin.y + windowFrame.size.height - impl->shadow_top > screenFrame.origin.y + screenFrame.size.height)
newOrigin.y = screenFrame.origin.y + screenFrame.size.height - windowFrame.size.height + impl->shadow_top;
[self setFrameOrigin:newOrigin];
return YES;
}
/* Used by gdkevents-quartz.c to decide if our sendEvent() handler above
* will see the event or if it will be subjected to standard processing
* by GDK.
*/
-(BOOL)isInManualResizeOrMove
{
return inManualResize || inManualMove;
}
-(void)beginManualMove
{
NSRect frame = [self frame];
if (inMove || inManualMove || inManualResize)
return;
inManualMove = YES;
initialMoveLocation = [self convertBaseToScreen:[self mouseLocationOutsideOfEventStream]];
initialMoveLocation.x -= frame.origin.x;
initialMoveLocation.y -= frame.origin.y;
}
- (BOOL)trackManualResize
{
NSPoint mouse_location;
NSRect new_frame;
float mdx, mdy, dw, dh, dx, dy;
NSSize min_size;
if (!inManualResize || inTrackManualResize)
return NO;
inTrackManualResize = YES;
mouse_location = [self convertBaseToScreen:[self mouseLocationOutsideOfEventStream]];
mdx = initialResizeLocation.x - mouse_location.x;
mdy = initialResizeLocation.y - mouse_location.y;
/* Set how a mouse location delta translates to changes in width,
* height and position.
*/
dw = dh = dx = dy = 0.0;
if (resizeEdge == GDK_SURFACE_EDGE_EAST ||
resizeEdge == GDK_SURFACE_EDGE_NORTH_EAST ||
resizeEdge == GDK_SURFACE_EDGE_SOUTH_EAST)
{
dw = -1.0;
}
if (resizeEdge == GDK_SURFACE_EDGE_NORTH ||
resizeEdge == GDK_SURFACE_EDGE_NORTH_WEST ||
resizeEdge == GDK_SURFACE_EDGE_NORTH_EAST)
{
dh = -1.0;
}
if (resizeEdge == GDK_SURFACE_EDGE_SOUTH ||
resizeEdge == GDK_SURFACE_EDGE_SOUTH_WEST ||
resizeEdge == GDK_SURFACE_EDGE_SOUTH_EAST)
{
dh = 1.0;
dy = -1.0;
}
if (resizeEdge == GDK_SURFACE_EDGE_WEST ||
resizeEdge == GDK_SURFACE_EDGE_NORTH_WEST ||
resizeEdge == GDK_SURFACE_EDGE_SOUTH_WEST)
{
dw = 1.0;
dx = -1.0;
}
/* Apply changes to the frame captured when we started resizing */
new_frame = initialResizeFrame;
new_frame.origin.x += mdx * dx;
new_frame.origin.y += mdy * dy;
new_frame.size.width += mdx * dw;
new_frame.size.height += mdy * dh;
/* In case the resulting window would be too small reduce the
* change to both size and position.
*/
min_size = [self contentMinSize];
if (new_frame.size.width < min_size.width)
{
if (dx)
new_frame.origin.x -= min_size.width - new_frame.size.width;
new_frame.size.width = min_size.width;
}
if (new_frame.size.height < min_size.height)
{
if (dy)
new_frame.origin.y -= min_size.height - new_frame.size.height;
new_frame.size.height = min_size.height;
}
/* We could also apply aspect ratio:
new_frame.size.height = new_frame.size.width / [self aspectRatio].width * [self aspectRatio].height;
*/
[self setFrame:new_frame display:YES];
/* Let the resizing be handled by GTK+. */
if (g_main_context_pending (NULL))
g_main_context_iteration (NULL, FALSE);
inTrackManualResize = NO;
return YES;
}
-(void)beginManualResize:(GdkSurfaceEdge)edge
{
if (inMove || inManualMove || inManualResize)
return;
inManualResize = YES;
resizeEdge = edge;
initialResizeFrame = [self frame];
initialResizeLocation = [self convertBaseToScreen:[self mouseLocationOutsideOfEventStream]];
}
static GdkDragContext *current_context = NULL;
static GdkDragAction
drag_operation_to_drag_action (NSDragOperation operation)
{
GdkDragAction result = 0;
/* GDK and Quartz drag operations do not map 1:1.
* This mapping represents about the best that we
* can come up.
*/
if (operation & NSDragOperationGeneric)
result |= GDK_ACTION_MOVE;
if (operation & NSDragOperationCopy)
result |= GDK_ACTION_COPY;
if (operation & NSDragOperationMove)
result |= GDK_ACTION_MOVE;
if (operation & NSDragOperationLink)
result |= GDK_ACTION_LINK;
return result;
}
static NSDragOperation
drag_action_to_drag_operation (GdkDragAction action)
{
NSDragOperation result = 0;
if (action & GDK_ACTION_COPY)
result |= NSDragOperationCopy;
if (action & GDK_ACTION_LINK)
result |= NSDragOperationLink;
if (action & GDK_ACTION_MOVE)
result |= NSDragOperationMove;
return result;
}
static void
update_context_from_dragging_info (id <NSDraggingInfo> sender)
{
GdkDragAction action;
g_assert (current_context != NULL);
GDK_QUARTZ_DRAG_CONTEXT (current_context)->dragging_info = sender;
action = drag_operation_to_drag_action ([sender draggingSourceOperationMask]);
gdk_drag_context_set_actions (current_context, action, action);
}
- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
GdkEvent *event;
GdkSurface *window;
if (current_context)
g_object_unref (current_context);
current_context = g_object_new (GDK_TYPE_QUARTZ_DRAG_CONTEXT,
"device", gdk_seat_get_pointer (gdk_display_get_default_seat (current_context->display)),
NULL);
update_context_from_dragging_info (sender);
window = [[self contentView] gdkSurface];
event = gdk_event_new (GDK_DRAG_ENTER);
event->dnd.window = g_object_ref (window);
event->dnd.send_event = FALSE;
event->dnd.context = g_object_ref (current_context);
event->dnd.time = GDK_CURRENT_TIME;
gdk_event_set_device (event, gdk_drag_context_get_device (current_context));
gdk_event_set_seat (event, gdk_device_get_seat (gdk_drag_context_get_device (current_context)));
_gdk_event_emit (event);
g_object_unref (event);
return NSDragOperationNone;
}
- (void)draggingEnded:(id <NSDraggingInfo>)sender
{
/* leave a note for the source about what action was taken */
if (_gdk_quartz_drag_source_context && current_context)
_gdk_quartz_drag_source_context->action = current_context->action;
if (current_context)
g_object_unref (current_context);
current_context = NULL;
}
- (void)draggingExited:(id <NSDraggingInfo>)sender
{
GdkEvent *event;
event = gdk_event_new (GDK_DRAG_LEAVE);
event->dnd.window = g_object_ref ([[self contentView] gdkSurface]);
event->dnd.send_event = FALSE;
event->dnd.context = g_object_ref (current_context);
event->dnd.time = GDK_CURRENT_TIME;
gdk_event_set_device (event, gdk_drag_context_get_device (current_context));
gdk_event_set_seat (event, gdk_device_get_seat (gdk_drag_context_get_device (current_context)));
_gdk_event_emit (event);
g_object_unref (event);
g_object_unref (current_context);
current_context = NULL;
}
- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
{
NSPoint point = [sender draggingLocation];
NSPoint screen_point = [self convertBaseToScreen:point];
GdkEvent *event;
int gx, gy;
update_context_from_dragging_info (sender);
_gdk_quartz_surface_nspoint_to_gdk_xy (screen_point, &gx, &gy);
event = gdk_event_new (GDK_DRAG_MOTION);
event->dnd.window = g_object_ref ([[self contentView] gdkSurface]);
event->dnd.send_event = FALSE;
event->dnd.context = g_object_ref (current_context);
event->dnd.time = GDK_CURRENT_TIME;
event->dnd.x_root = gx;
event->dnd.y_root = gy;
gdk_event_set_device (event, gdk_drag_context_get_device (current_context));
gdk_event_set_seat (event, gdk_device_get_seat (gdk_drag_context_get_device (current_context)));
_gdk_event_emit (event);
g_object_unref (event);
return drag_action_to_drag_operation (current_context->action);
}
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
NSPoint point = [sender draggingLocation];
NSPoint screen_point = [self convertBaseToScreen:point];
GdkEvent *event;
int gy, gx;
update_context_from_dragging_info (sender);
_gdk_quartz_surface_nspoint_to_gdk_xy (screen_point, &gx, &gy);
event = gdk_event_new (GDK_DROP_START);
event->dnd.window = g_object_ref ([[self contentView] gdkSurface]);
event->dnd.send_event = FALSE;
event->dnd.context = g_object_ref (current_context);
event->dnd.time = GDK_CURRENT_TIME;
event->dnd.x_root = gx;
event->dnd.y_root = gy;
gdk_event_set_device (event, gdk_drag_context_get_device (current_context));
gdk_event_set_seat (event, gdk_device_get_seat (gdk_drag_context_get_device (current_context)));
_gdk_event_emit (event);
g_object_unref (event);
g_object_unref (current_context);
current_context = NULL;
return YES;
}
- (BOOL)wantsPeriodicDraggingUpdates
{
return NO;
}
- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation
{
GdkEvent *event;
GdkDisplay *display;
GdkDevice *device;
g_assert (_gdk_quartz_drag_source_context != NULL);
event = gdk_event_new (GDK_DROP_FINISHED);
event->dnd.window = g_object_ref ([[self contentView] gdkSurface]);
event->dnd.send_event = FALSE;
event->dnd.context = g_object_ref (_gdk_quartz_drag_source_context);
display = gdk_surface_get_display (event->dnd.window);
if (display)
{
GList* windows, *list;
gint gx, gy;
event->dnd.context->dest_surface = NULL;
windows = get_toplevels ();
_gdk_quartz_surface_nspoint_to_gdk_xy (aPoint, &gx, &gy);
for (list = windows; list; list = list->next)
{
GdkSurface* win = (GdkSurface*) list->data;
gint wx, wy;
gint ww, wh;
gdk_surface_get_root_origin (win, &wx, &wy);
ww = gdk_surface_get_width (win);
wh = gdk_surface_get_height (win);
if (gx > wx && gy > wy && gx <= wx + ww && gy <= wy + wh)
event->dnd.context->dest_surface = win;
}
}
device = gdk_drag_context_get_device (_gdk_quartz_drag_source_context);
gdk_event_set_device (event, device);
gdk_event_set_seat (event, gdk_device_get_seat (device));
_gdk_event_emit (event);
g_object_unref (event);
g_object_unref (_gdk_quartz_drag_source_context);
_gdk_quartz_drag_source_context = NULL;
}
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
- (void)setStyleMask:(NSUInteger)styleMask
{
gboolean was_fullscreen;
gboolean is_fullscreen;
was_fullscreen = (([self styleMask] & NSFullScreenWindowMask) != 0);
[super setStyleMask:styleMask];
is_fullscreen = (([self styleMask] & NSFullScreenWindowMask) != 0);
if (was_fullscreen != is_fullscreen)
_gdk_quartz_surface_update_fullscreen_state ([[self contentView] gdkSurface]);
}
#endif
- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
{
NSRect rect;
GdkSurface *window = [[self contentView] gdkSurface];
GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
/* Allow the window to move up "shadow_top" more than normally allowed
* by the default impl. This makes it possible to move windows with
* client side shadow right up to the screen's menu bar. */
rect = [super constrainFrameRect:frameRect toScreen:screen];
if (frameRect.origin.y > rect.origin.y)
rect.origin.y = MIN (frameRect.origin.y, rect.origin.y + impl->shadow_top);
return rect;
}
- (NSRect)windowWillUseStandardFrame:(NSWindow *)nsWindow
defaultFrame:(NSRect)newFrame
{
NSRect screenFrame = [[self screen] visibleFrame];
GdkSurface *window = [[self contentView] gdkSurface];
GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
gboolean maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
if (!maximized)
return screenFrame;
else
return lastUnmaximizedFrame;
}
- (BOOL)windowShouldZoom:(NSWindow *)nsWindow
toFrame:(NSRect)newFrame
{
GdkSurface *window = [[self contentView] gdkSurface];
GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (window->impl);
gboolean maximized = gdk_surface_get_state (window) & GDK_SURFACE_STATE_MAXIMIZED;
if (maximized)
{
lastMaximizedFrame = newFrame;
gdk_synthesize_surface_state (window,
GDK_SURFACE_STATE_MAXIMIZED,
0);
}
else
{
lastUnmaximizedFrame = [nsWindow frame];
gdk_synthesize_surface_state (window,
0,
GDK_SURFACE_STATE_MAXIMIZED);
}
inMaximizeTransition = YES;
return YES;
}
-(void)windowDidEndLiveResize:(NSNotification *)aNotification
{
inMaximizeTransition = NO;
}
-(NSSize)window:(NSWindow *)window willUseFullScreenContentSize:(NSSize)proposedSize
{
return [[window screen] frame].size;
}
-(void)windowWillEnterFullScreen:(NSNotification *)aNotification
{
lastUnfullscreenFrame = [self frame];
}
-(void)windowWillExitFullScreen:(NSNotification *)aNotification
{
[self setFrame:lastUnfullscreenFrame display:YES];
}
@end

View File

@ -1,61 +0,0 @@
/* GdkQuartzNSWindow.h
*
* Copyright (C) 2005-2007 Imendio AB
*
* 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/>.
*/
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#include <glib.h>
#include <gdk.h>
@interface GdkQuartzNSWindow : NSWindow {
BOOL inMove;
BOOL inShowOrHide;
BOOL initialPositionKnown;
/* Manually triggered move/resize (not by the window manager) */
BOOL inManualMove;
BOOL inManualResize;
BOOL inTrackManualResize;
NSPoint initialMoveLocation;
NSPoint initialResizeLocation;
NSRect initialResizeFrame;
GdkSurfaceEdge resizeEdge;
NSRect lastUnmaximizedFrame;
NSRect lastMaximizedFrame;
NSRect lastUnfullscreenFrame;
BOOL inMaximizeTransition;
}
-(BOOL)isInMove;
-(void)beginManualMove;
-(BOOL)trackManualMove;
-(BOOL)isInManualResizeOrMove;
-(void)beginManualResize:(GdkSurfaceEdge)edge;
-(BOOL)trackManualResize;
-(void)showAndMakeKey:(BOOL)makeKey;
-(void)hide;
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
-(void)setStyleMask:(NSUInteger)styleMask;
#endif
@end

View File

@ -1,712 +0,0 @@
/* GdkQuartzView.m
*
* Copyright (C) 2005-2007 Imendio AB
* Copyright (C) 2011 Hiroyuki Yamamoto
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#import "GdkQuartzView.h"
#include "gdkquartzsurface.h"
#include "gdkprivate-quartz.h"
#include "gdkquartz.h"
@implementation GdkQuartzView
-(id)initWithFrame: (NSRect)frameRect
{
if ((self = [super initWithFrame: frameRect]))
{
markedRange = NSMakeRange (NSNotFound, 0);
selectedRange = NSMakeRange (NSNotFound, 0);
}
return self;
}
-(BOOL)acceptsFirstResponder
{
GDK_NOTE (EVENTS, g_message ("acceptsFirstResponder"));
return YES;
}
-(BOOL)becomeFirstResponder
{
GDK_NOTE (EVENTS, g_message ("becomeFirstResponder"));
return YES;
}
-(BOOL)resignFirstResponder
{
GDK_NOTE (EVENTS, g_message ("resignFirstResponder"));
return YES;
}
-(void) keyDown: (NSEvent *) theEvent
{
GDK_NOTE (EVENTS, g_message ("keyDown"));
[self interpretKeyEvents: [NSArray arrayWithObject: theEvent]];
}
-(void)flagsChanged: (NSEvent *) theEvent
{
}
-(NSUInteger)characterIndexForPoint: (NSPoint)aPoint
{
GDK_NOTE (EVENTS, g_message ("characterIndexForPoint"));
return 0;
}
-(NSRect)firstRectForCharacterRange: (NSRange)aRange actualRange: (NSRangePointer)actualRange
{
GDK_NOTE (EVENTS, g_message ("firstRectForCharacterRange"));
gint ns_x, ns_y;
GdkRectangle *rect;
rect = g_object_get_data (G_OBJECT (gdk_surface), GIC_CURSOR_RECT);
if (rect)
{
_gdk_quartz_surface_gdk_xy_to_xy (rect->x, rect->y + rect->height,
&ns_x, &ns_y);
return NSMakeRect (ns_x, ns_y, rect->width, rect->height);
}
else
{
return NSMakeRect (0, 0, 0, 0);
}
}
-(NSArray *)validAttributesForMarkedText
{
GDK_NOTE (EVENTS, g_message ("validAttributesForMarkedText"));
return [NSArray arrayWithObjects: NSUnderlineStyleAttributeName, nil];
}
-(NSAttributedString *)attributedSubstringForProposedRange: (NSRange)aRange actualRange: (NSRangePointer)actualRange
{
GDK_NOTE (EVENTS, g_message ("attributedSubstringForProposedRange"));
return nil;
}
-(BOOL)hasMarkedText
{
GDK_NOTE (EVENTS, g_message ("hasMarkedText"));
return markedRange.location != NSNotFound && markedRange.length != 0;
}
-(NSRange)markedRange
{
GDK_NOTE (EVENTS, g_message ("markedRange"));
return markedRange;
}
-(NSRange)selectedRange
{
GDK_NOTE (EVENTS, g_message ("selectedRange"));
return selectedRange;
}
-(void)unmarkText
{
GDK_NOTE (EVENTS, g_message ("unmarkText"));
gchar *prev_str;
markedRange = selectedRange = NSMakeRange (NSNotFound, 0);
g_object_set_data_full (G_OBJECT (gdk_surface), TIC_MARKED_TEXT, NULL, g_free);
}
-(void)setMarkedText: (id)aString selectedRange: (NSRange)newSelection replacementRange: (NSRange)replacementRange
{
GDK_NOTE (EVENTS, g_message ("setMarkedText"));
const char *str;
gchar *prev_str;
if (replacementRange.location == NSNotFound)
{
markedRange = NSMakeRange (newSelection.location, [aString length]);
selectedRange = NSMakeRange (newSelection.location, newSelection.length);
}
else {
markedRange = NSMakeRange (replacementRange.location, [aString length]);
selectedRange = NSMakeRange (replacementRange.location + newSelection.location, newSelection.length);
}
if ([aString isKindOfClass: [NSAttributedString class]])
{
str = [[aString string] UTF8String];
}
else {
str = [aString UTF8String];
}
g_object_set_data_full (G_OBJECT (gdk_surface), TIC_MARKED_TEXT, g_strdup (str), g_free);
g_object_set_data (G_OBJECT (gdk_surface), TIC_SELECTED_POS,
GUINT_TO_POINTER (selectedRange.location));
g_object_set_data (G_OBJECT (gdk_surface), TIC_SELECTED_LEN,
GUINT_TO_POINTER (selectedRange.length));
GDK_NOTE (EVENTS, g_message ("setMarkedText: set %s (%p, nsview %p): %s",
TIC_MARKED_TEXT, gdk_surface, self,
str ? str : "(empty)"));
/* handle text input changes by mouse events */
if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (gdk_surface),
TIC_IN_KEY_DOWN)))
{
_gdk_quartz_synthesize_null_key_event(gdk_surface);
}
}
-(void)doCommandBySelector: (SEL)aSelector
{
GDK_NOTE (EVENTS, g_message ("doCommandBySelector"));
if ([self respondsToSelector: aSelector])
[self performSelector: aSelector];
}
-(void)insertText: (id)aString replacementRange: (NSRange)replacementRange
{
GDK_NOTE (EVENTS, g_message ("insertText"));
const char *str;
NSString *string;
gchar *prev_str;
if ([self hasMarkedText])
[self unmarkText];
if ([aString isKindOfClass: [NSAttributedString class]])
string = [aString string];
else
string = aString;
NSCharacterSet *ctrlChars = [NSCharacterSet controlCharacterSet];
NSCharacterSet *wsnlChars = [NSCharacterSet whitespaceAndNewlineCharacterSet];
if ([string rangeOfCharacterFromSet:ctrlChars].length &&
[string rangeOfCharacterFromSet:wsnlChars].length == 0)
{
/* discard invalid text input with Chinese input methods */
str = "";
[self unmarkText];
NSInputManager *currentInputManager = [NSInputManager currentInputManager];
[currentInputManager markedTextAbandoned:self];
}
else
{
str = [string UTF8String];
}
g_object_set_data_full (G_OBJECT (gdk_surface), TIC_INSERT_TEXT, g_strdup (str), g_free);
GDK_NOTE (EVENTS, g_message ("insertText: set %s (%p, nsview %p): %s",
TIC_INSERT_TEXT, gdk_surface, self,
str ? str : "(empty)"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_FILTERED));
/* handle text input changes by mouse events */
if (!GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (gdk_surface),
TIC_IN_KEY_DOWN)))
{
_gdk_quartz_synthesize_null_key_event(gdk_surface);
}
}
-(void)deleteBackward: (id)sender
{
GDK_NOTE (EVENTS, g_message ("deleteBackward"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)deleteForward: (id)sender
{
GDK_NOTE (EVENTS, g_message ("deleteForward"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)deleteToBeginningOfLine: (id)sender
{
GDK_NOTE (EVENTS, g_message ("deleteToBeginningOfLine"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)deleteToEndOfLine: (id)sender
{
GDK_NOTE (EVENTS, g_message ("deleteToEndOfLine"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)deleteWordBackward: (id)sender
{
GDK_NOTE (EVENTS, g_message ("deleteWordBackward"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)deleteWordForward: (id)sender
{
GDK_NOTE (EVENTS, g_message ("deleteWordForward"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)insertBacktab: (id)sender
{
GDK_NOTE (EVENTS, g_message ("insertBacktab"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)insertNewline: (id)sender
{
GDK_NOTE (EVENTS, g_message ("insertNewline"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY, GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)insertTab: (id)sender
{
GDK_NOTE (EVENTS, g_message ("insertTab"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveBackward: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveBackward"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveBackwardAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveBackwardAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveDown: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveDown"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveDownAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveDownAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveForward: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveForward"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveForwardAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveForwardAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveLeft: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveLeft"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveLeftAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveLeftAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveRight: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveRight"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveRightAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveRightAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToBeginningOfDocument: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToBeginningOfDocument"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToBeginningOfDocumentAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToBeginningOfDocumentAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToBeginningOfLine: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToBeginningOfLine"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToBeginningOfLineAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToBeginningOfLineAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToEndOfDocument: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToEndOfDocument"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToEndOfDocumentAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToEndOfDocumentAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToEndOfLine: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToEndOfLine"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveToEndOfLineAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveToEndOfLineAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveUp: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveUp"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveUpAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveUpAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordBackward: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordBackward"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordBackwardAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordBackwardAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordForward: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordForward"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordForwardAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordForwardAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordLeft: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordLeft"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordLeftAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordLeftAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordRight: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordRight"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)moveWordRightAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("moveWordRightAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)pageDown: (id)sender
{
GDK_NOTE (EVENTS, g_message ("pageDown"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)pageDownAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("pageDownAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)pageUp: (id)sender
{
GDK_NOTE (EVENTS, g_message ("pageUp"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)pageUpAndModifySelection: (id)sender
{
GDK_NOTE (EVENTS, g_message ("pageUpAndModifySelection"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)selectAll: (id)sender
{
GDK_NOTE (EVENTS, g_message ("selectAll"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)selectLine: (id)sender
{
GDK_NOTE (EVENTS, g_message ("selectLine"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)selectWord: (id)sender
{
GDK_NOTE (EVENTS, g_message ("selectWord"));
g_object_set_data (G_OBJECT (gdk_surface), GIC_FILTER_KEY,
GUINT_TO_POINTER (GIC_FILTER_PASSTHRU));
}
-(void)noop: (id)sender
{
GDK_NOTE (EVENTS, g_message ("noop"));
}
/* --------------------------------------------------------------- */
-(void)dealloc
{
if (trackingRect)
{
[self removeTrackingRect: trackingRect];
trackingRect = 0;
}
[super dealloc];
}
-(void)setGdkSurface: (GdkSurface *)window
{
gdk_surface = window;
}
-(GdkSurface *)gdkSurface
{
return gdk_surface;
}
-(NSTrackingRectTag)trackingRect
{
return trackingRect;
}
-(BOOL)isFlipped
{
return YES;
}
-(BOOL)isOpaque
{
if (GDK_SURFACE_DESTROYED (gdk_surface))
return YES;
return NO;
}
-(void)drawRect: (NSRect)rect
{
GdkRectangle gdk_rect;
GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (gdk_window->impl);
const NSRect *drawn_rects;
NSInteger count;
int i;
cairo_region_t *region;
if (GDK_SURFACE_DESTROYED (gdk_surface))
return;
if (! (gdk_window->event_mask & GDK_EXPOSURE_MASK))
return;
if (NSEqualRects (rect, NSZeroRect))
return;
if (!GDK_SURFACE_IS_MAPPED (gdk_surface))
{
/* If the window is not yet mapped, clip_region_with_children
* will be empty causing the usual code below to draw nothing.
* To not see garbage on the screen, we draw an aesthetic color
* here. The garbage would be visible if any widget enabled
* the NSView's CALayer in order to add sublayers for custom
* native rendering.
*/
[NSGraphicsContext saveGraphicsState];
[[NSColor windowBackgroundColor] setFill];
[NSBezierPath fillRect: rect];
[NSGraphicsContext restoreGraphicsState];
return;
}
/* Clear our own bookkeeping of regions that need display */
if (impl->needs_display_region)
{
cairo_region_destroy (impl->needs_display_region);
impl->needs_display_region = NULL;
}
[self getRectsBeingDrawn: &drawn_rects count: &count];
region = cairo_region_create ();
for (i = 0; i < count; i++)
{
gdk_rect.x = drawn_rects[i].origin.x;
gdk_rect.y = drawn_rects[i].origin.y;
gdk_rect.width = drawn_rects[i].size.width;
gdk_rect.height = drawn_rects[i].size.height;
cairo_region_union_rectangle (region, &gdk_rect);
}
impl->in_paint_rect_count++;
_gdk_surface_process_updates_recurse (gdk_surface, region);
impl->in_paint_rect_count--;
cairo_region_destroy (region);
if (needsInvalidateShadow)
{
[[self window] invalidateShadow];
needsInvalidateShadow = NO;
}
}
-(void)setNeedsInvalidateShadow: (BOOL)invalidate
{
needsInvalidateShadow = invalidate;
}
/* For information on setting up tracking rects properly, see here:
* http://developer.apple.com/documentation/Cocoa/Conceptual/EventOverview/EventOverview.pdf
*/
-(void)updateTrackingRect
{
GdkSurfaceImplQuartz *impl = GDK_SURFACE_IMPL_QUARTZ (gdk_window->impl);
NSRect rect;
if (!impl || !impl->toplevel)
return;
if (trackingRect)
{
[self removeTrackingRect: trackingRect];
trackingRect = 0;
}
if (!impl->toplevel)
return;
/* Note, if we want to set assumeInside we can use:
* NSPointInRect ([[self window] convertScreenToBase:[NSEvent mouseLocation]], rect)
*/
rect = [self bounds];
trackingRect = [self addTrackingRect: rect
owner: self
userData: nil
assumeInside: NO];
}
-(void)viewDidMoveToWindow
{
if (![self window]) /* We are destroyed already */
return;
[self updateTrackingRect];
}
-(void)viewWillMoveToWindow: (NSWindow *)newWindow
{
if (newWindow == nil && trackingRect)
{
[self removeTrackingRect: trackingRect];
trackingRect = 0;
}
}
-(void)setFrame: (NSRect)frame
{
[super setFrame: frame];
if ([self window])
[self updateTrackingRect];
}
@end

View File

@ -1,36 +0,0 @@
/* GDK - The GIMP Drawing Kit
*
* Copyright © 2018 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkconfig.h"
#include "gdkcairocontext-quartz.h"
G_DEFINE_TYPE (GdkQuartzCairoContext, gdk_quartz_cairo_context, GDK_TYPE_CAIRO_CONTEXT)
static void
gdk_quartz_cairo_context_class_init (GdkQuartzCairoContextClass *klass)
{
}
static void
gdk_quartz_cairo_context_init (GdkQuartzCairoContext *self)
{
}

View File

@ -1,53 +0,0 @@
/* GDK - The GIMP Drawing Kit
*
* Copyright © 2018 Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_CAIRO_CONTEXT__
#define __GDK_QUARTZ_CAIRO_CONTEXT__
#include "gdkconfig.h"
#include "gdkcairocontextprivate.h"
G_BEGIN_DECLS
#define GDK_TYPE_QUARTZ_CAIRO_CONTEXT (gdk_quartz_cairo_context_get_type ())
#define GDK_QUARTZ_CAIRO_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_QUARTZ_CAIRO_CONTEXT, GdkQuartzCairoContext))
#define GDK_IS_QUARTZ_CAIRO_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_QUARTZ_CAIRO_CONTEXT))
#define GDK_QUARTZ_CAIRO_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_CAIRO_CONTEXT, GdkQuartzCairoContextClass))
#define GDK_IS_QUARTZ_CAIRO_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_CAIRO_CONTEXT))
#define GDK_QUARTZ_CAIRO_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_CAIRO_CONTEXT, GdkQuartzCairoContextClass))
typedef struct _GdkQuartzCairoContext GdkQuartzCairoContext;
typedef struct _GdkQuartzCairoContextClass GdkQuartzCairoContextClass;
struct _GdkQuartzCairoContext
{
GdkCairoContext parent_instance;
};
struct _GdkQuartzCairoContextClass
{
GdkCairoContextClass parent_class;
};
GDK_AVAILABLE_IN_ALL
GType gdk_quartz_cairo_context_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GDK_QUARTZ_CAIRO_CONTEXT__ */

View File

@ -1,482 +0,0 @@
/* gdkcursor-quartz.c
*
* Copyright (C) 2005-2007 Imendio AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkdisplay.h"
#include "gdkcursor.h"
#include "gdkcursorprivate.h"
#include "gdkquartzcursor.h"
#include "gdkprivate-quartz.h"
#include "xcursors.h"
struct _GdkQuartzCursor
{
GdkCursor cursor;
NSCursor *nscursor;
};
struct _GdkQuartzCursorClass
{
GdkCursorClass cursor_class;
};
static GdkCursor *cached_xcursors[G_N_ELEMENTS (xcursors)];
static GdkCursor *
gdk_quartz_cursor_new_from_nscursor (NSCursor *nscursor,
GdkCursorType cursor_type)
{
GdkQuartzCursor *private;
private = g_object_new (GDK_TYPE_QUARTZ_CURSOR,
"cursor-type", cursor_type,
"display", _gdk_display,
NULL);
private->nscursor = nscursor;
return GDK_CURSOR (private);
}
static GdkCursor *
create_blank_cursor (void)
{
NSCursor *nscursor;
NSImage *nsimage;
NSSize size = { 1.0, 1.0 };
nsimage = [[NSImage alloc] initWithSize:size];
nscursor = [[NSCursor alloc] initWithImage:nsimage
hotSpot:NSMakePoint(0.0, 0.0)];
[nsimage release];
return gdk_quartz_cursor_new_from_nscursor (nscursor, GDK_BLANK_CURSOR);
}
static gboolean
get_bit (const guchar *data,
gint width,
gint height,
gint x,
gint y)
{
gint bytes_per_line;
const guchar *src;
if (x < 0 || y < 0 || x >= width || y >= height)
return FALSE;
bytes_per_line = (width + 7) / 8;
src = &data[y * bytes_per_line];
return ((src[x / 8] >> x % 8) & 1);
}
static GdkCursor *
create_builtin_cursor (GdkCursorType cursor_type)
{
GdkCursor *cursor;
NSBitmapImageRep *bitmap_rep;
NSInteger mask_width, mask_height;
gint src_width, src_height;
gint dst_stride;
const guchar *mask_start, *src_start;
gint dx, dy;
gint x, y;
NSPoint hotspot;
NSImage *image;
NSCursor *nscursor;
if (cursor_type >= G_N_ELEMENTS (xcursors) || cursor_type < 0)
return NULL;
cursor = cached_xcursors[cursor_type];
if (cursor)
return cursor;
GDK_QUARTZ_ALLOC_POOL;
src_width = xcursors[cursor_type].width;
src_height = xcursors[cursor_type].height;
mask_width = xcursors[cursor_type+1].width;
mask_height = xcursors[cursor_type+1].height;
bitmap_rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:mask_width pixelsHigh:mask_height
bitsPerSample:8 samplesPerPixel:4
hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:0 bitsPerPixel:0];
dst_stride = [bitmap_rep bytesPerRow];
src_start = xcursors[cursor_type].bits;
mask_start = xcursors[cursor_type+1].bits;
dx = xcursors[cursor_type+1].hotx - xcursors[cursor_type].hotx;
dy = xcursors[cursor_type+1].hoty - xcursors[cursor_type].hoty;
for (y = 0; y < mask_height; y++)
{
guchar *dst = [bitmap_rep bitmapData] + y * dst_stride;
for (x = 0; x < mask_width; x++)
{
if (get_bit (mask_start, mask_width, mask_height, x, y))
{
if (get_bit (src_start, src_width, src_height, x - dx, y - dy))
{
*dst++ = 0;
*dst++ = 0;
*dst++ = 0;
}
else
{
*dst++ = 0xff;
*dst++ = 0xff;
*dst++ = 0xff;
}
*dst++ = 0xff;
}
else
{
*dst++ = 0;
*dst++ = 0;
*dst++ = 0;
*dst++ = 0;
}
}
}
image = [[NSImage alloc] init];
[image addRepresentation:bitmap_rep];
[bitmap_rep release];
hotspot = NSMakePoint (xcursors[cursor_type+1].hotx,
xcursors[cursor_type+1].hoty);
nscursor = [[NSCursor alloc] initWithImage:image hotSpot:hotspot];
[image release];
cursor = gdk_quartz_cursor_new_from_nscursor (nscursor, GDK_CURSOR_IS_PIXMAP);
cached_xcursors[cursor_type] = g_object_ref (cursor);
GDK_QUARTZ_RELEASE_POOL;
return cursor;
}
GdkCursor*
_gdk_quartz_display_get_cursor_for_type (GdkDisplay *display,
GdkCursorType cursor_type)
{
NSCursor *nscursor;
g_return_val_if_fail (display == gdk_display_get_default (), NULL);
switch (cursor_type)
{
case GDK_XTERM:
nscursor = [NSCursor IBeamCursor];
break;
case GDK_SB_H_DOUBLE_ARROW:
nscursor = [NSCursor resizeLeftRightCursor];
break;
case GDK_SB_V_DOUBLE_ARROW:
nscursor = [NSCursor resizeUpDownCursor];
break;
case GDK_SB_UP_ARROW:
case GDK_BASED_ARROW_UP:
case GDK_BOTTOM_TEE:
case GDK_TOP_SIDE:
nscursor = [NSCursor resizeUpCursor];
break;
case GDK_SB_DOWN_ARROW:
case GDK_BASED_ARROW_DOWN:
case GDK_TOP_TEE:
case GDK_BOTTOM_SIDE:
nscursor = [NSCursor resizeDownCursor];
break;
case GDK_SB_LEFT_ARROW:
case GDK_RIGHT_TEE:
case GDK_LEFT_SIDE:
nscursor = [NSCursor resizeLeftCursor];
break;
case GDK_SB_RIGHT_ARROW:
case GDK_LEFT_TEE:
case GDK_RIGHT_SIDE:
nscursor = [NSCursor resizeRightCursor];
break;
case GDK_TCROSS:
case GDK_CROSS:
case GDK_CROSSHAIR:
case GDK_DIAMOND_CROSS:
nscursor = [NSCursor crosshairCursor];
break;
case GDK_HAND1:
case GDK_HAND2:
nscursor = [NSCursor pointingHandCursor];
break;
case GDK_CURSOR_IS_PIXMAP:
return NULL;
case GDK_BLANK_CURSOR:
return create_blank_cursor ();
default:
return g_object_ref (create_builtin_cursor (cursor_type));
}
[nscursor retain];
return gdk_quartz_cursor_new_from_nscursor (nscursor, cursor_type);
}
GdkCursor *
_gdk_quartz_display_get_cursor_for_surface (GdkDisplay *display,
cairo_surface_t *surface,
gdouble x,
gdouble y)
{
NSImage *image;
NSCursor *nscursor;
GdkCursor *cursor;
GdkPixbuf *pixbuf;
GDK_QUARTZ_ALLOC_POOL;
pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0,
cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface));
image = gdk_quartz_pixbuf_to_ns_image_libgtk_only (pixbuf);
nscursor = [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint(x, y)];
cursor = gdk_quartz_cursor_new_from_nscursor (nscursor, GDK_CURSOR_IS_PIXMAP);
g_object_unref (pixbuf);
GDK_QUARTZ_RELEASE_POOL;
return cursor;
}
/* OS X only exports a number of cursor types in its public NSCursor interface.
* By overriding the private _coreCursorType method, we can tell OS X to load
* one of its internal cursors instead (since cursor images are loaded on demand
* instead of in advance). WebKit does this too.
*/
@interface gdkCoreCursor : NSCursor {
@private
int type;
BOOL override;
}
@end
@implementation gdkCoreCursor
- (int)_coreCursorType
{
if (self->override)
return self->type;
return [super _coreCursorType];
}
#define CUSTOM_CURSOR_CTOR(name, id) \
+ (gdkCoreCursor *)name \
{ \
gdkCoreCursor *obj; \
obj = [self new]; \
if (obj) { \
obj->override = YES; \
obj->type = id; \
} \
return obj; \
}
CUSTOM_CURSOR_CTOR(gdkHelpCursor, 40)
CUSTOM_CURSOR_CTOR(gdkProgressCursor, 4)
/* TODO OS X doesn't seem to have a way to get this. There is an undocumented
* method +[NSCursor _waitCursor], but it doesn't actually return this cursor,
* but rather some odd low-quality non-animating version of this cursor. Use
* the progress cursor instead for now.
*/
CUSTOM_CURSOR_CTOR(gdkWaitCursor, 4)
CUSTOM_CURSOR_CTOR(gdkAliasCursor, 2)
CUSTOM_CURSOR_CTOR(gdkMoveCursor, 39)
/* TODO OS X doesn't seem to provide one; copy the move cursor for now
* since it looks similar to what we want. */
CUSTOM_CURSOR_CTOR(gdkAllScrollCursor, 39)
CUSTOM_CURSOR_CTOR(gdkNEResizeCursor, 29)
CUSTOM_CURSOR_CTOR(gdkNWResizeCursor, 33)
CUSTOM_CURSOR_CTOR(gdkSEResizeCursor, 35)
CUSTOM_CURSOR_CTOR(gdkSWResizeCursor, 37)
CUSTOM_CURSOR_CTOR(gdkEWResizeCursor, 28)
CUSTOM_CURSOR_CTOR(gdkNSResizeCursor, 32)
CUSTOM_CURSOR_CTOR(gdkNESWResizeCursor, 30)
CUSTOM_CURSOR_CTOR(gdkNWSEResizeCursor, 34)
CUSTOM_CURSOR_CTOR(gdkZoomInCursor, 42)
CUSTOM_CURSOR_CTOR(gdkZoomOutCursor, 43)
@end
struct CursorsByName {
const gchar *name;
NSString *selector;
};
static const struct CursorsByName cursors_by_name[] = {
/* Link & Status */
{ "context-menu", @"contextualMenuCursor" },
{ "help", @"gdkHelpCursor" },
{ "pointer", @"pointingHandCursor" },
{ "progress", @"gdkProgressCursor" },
{ "wait", @"gdkWaitCursor" },
/* Selection */
{ "cell", @"crosshairCursor" },
{ "crosshair", @"crosshairCursor" },
{ "text", @"IBeamCursor" },
{ "vertical-text", @"IBeamCursorForVerticalLayout" },
/* Drag & Drop */
{ "alias", @"gdkAliasCursor" },
{ "copy", @"dragCopyCursor" },
{ "move", @"gdkMoveCursor" },
{ "no-drop", @"operationNotAllowedCursor" },
{ "not-allowed", @"operationNotAllowedCursor" },
{ "grab", @"openHandCursor" },
{ "grabbing", @"closedHandCursor" },
/* Resize & Scrolling */
{ "all-scroll", @"gdkAllScrollCursor" },
{ "col-resize", @"resizeLeftRightCursor" },
{ "row-resize", @"resizeUpDownCursor" },
{ "n-resize", @"resizeUpCursor" },
{ "e-resize", @"resizeRightCursor" },
{ "s-resize", @"resizeDownCursor" },
{ "w-resize", @"resizeLeftCursor" },
{ "ne-resize", @"gdkNEResizeCursor" },
{ "nw-resize", @"gdkNWResizeCursor" },
{ "se-resize", @"gdkSEResizeCursor" },
{ "sw-resize", @"gdkSWResizeCursor" },
{ "ew-resize", @"gdkEWResizeCursor" },
{ "ns-resize", @"gdkNSResizeCursor" },
{ "nesw-resize", @"gdkNESWResizeCursor" },
{ "nwse-resize", @"gdkNWSEResizeCursor" },
/* Zoom */
{ "zoom-in", @"gdkZoomInCursor" },
{ "zoom-out", @"gdkZoomOutCursor" },
{ NULL, NULL },
};
GdkCursor*
_gdk_quartz_display_get_cursor_for_name (GdkDisplay *display,
const gchar *name)
{
NSCursor *nscursor;
const struct CursorsByName *test;
SEL selector;
if (name == NULL || g_str_equal (name, "none"))
return create_blank_cursor ();
// use this selector if nothing found
selector = @selector(arrowCursor);
for (test = cursors_by_name; test->name != NULL; test++)
if (g_str_equal (name, test->name))
{
selector = NSSelectorFromString(test->selector);
break;
}
nscursor = [[gdkCoreCursor class] performSelector:selector];
[nscursor retain];
return gdk_quartz_cursor_new_from_nscursor (nscursor, GDK_CURSOR_IS_PIXMAP);
}
G_DEFINE_TYPE (GdkQuartzCursor, gdk_quartz_cursor, GDK_TYPE_CURSOR)
static void
gdk_quartz_cursor_finalize (GObject *object)
{
GdkQuartzCursor *private = GDK_QUARTZ_CURSOR (object);
if (private->nscursor)
[private->nscursor release];
private->nscursor = NULL;
}
static void
gdk_quartz_cursor_class_init (GdkQuartzCursorClass *quartz_cursor_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (quartz_cursor_class);
object_class->finalize = gdk_quartz_cursor_finalize;
}
static void
gdk_quartz_cursor_init (GdkQuartzCursor *cursor)
{
}
gboolean
_gdk_quartz_display_supports_cursor_alpha (GdkDisplay *display)
{
return TRUE;
}
gboolean
_gdk_quartz_display_supports_cursor_color (GdkDisplay *display)
{
return TRUE;
}
void
_gdk_quartz_display_get_default_cursor_size (GdkDisplay *display,
guint *width,
guint *height)
{
/* Mac OS X doesn't have the notion of a default size */
*width = 32;
*height = 32;
}
void
_gdk_quartz_display_get_maximal_cursor_size (GdkDisplay *display,
guint *width,
guint *height)
{
/* Cursor sizes in Mac OS X can be arbitrarily large */
*width = 65536;
*height = 65536;
}
NSCursor *
_gdk_quartz_cursor_get_ns_cursor (GdkCursor *cursor)
{
GdkQuartzCursor *cursor_private;
if (!cursor)
return [NSCursor arrowCursor];
g_return_val_if_fail (GDK_IS_QUARTZ_CURSOR (cursor), NULL);
cursor_private = GDK_QUARTZ_CURSOR (cursor);
return cursor_private->nscursor;
}

View File

@ -1,347 +0,0 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
* Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gdk/gdkdeviceprivate.h>
#include <gdk/gdkdisplayprivate.h>
#import "GdkQuartzView.h"
#include "gdkquartzsurface.h"
#include "gdkquartzcursor.h"
#include "gdkprivate-quartz.h"
#include "gdkquartzdevice-core.h"
struct _GdkQuartzDeviceCore
{
GdkDevice parent_instance;
};
struct _GdkQuartzDeviceCoreClass
{
GdkDeviceClass parent_class;
};
static gboolean gdk_quartz_device_core_get_history (GdkDevice *device,
GdkSurface *window,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events);
static void gdk_quartz_device_core_get_state (GdkDevice *device,
GdkSurface *window,
gdouble *axes,
GdkModifierType *mask);
static void gdk_quartz_device_core_set_surface_cursor (GdkDevice *device,
GdkSurface *window,
GdkCursor *cursor);
static void gdk_quartz_device_core_warp (GdkDevice *device,
gdouble x,
gdouble y);
static void gdk_quartz_device_core_query_state (GdkDevice *device,
GdkSurface *window,
GdkSurface **root_window,
GdkSurface **child_window,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask);
static GdkGrabStatus gdk_quartz_device_core_grab (GdkDevice *device,
GdkSurface *window,
gboolean owner_events,
GdkEventMask event_mask,
GdkSurface *confine_to,
GdkCursor *cursor,
guint32 time_);
static void gdk_quartz_device_core_ungrab (GdkDevice *device,
guint32 time_);
static GdkSurface * gdk_quartz_device_core_surface_at_position (GdkDevice *device,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel);
G_DEFINE_TYPE (GdkQuartzDeviceCore, gdk_quartz_device_core, GDK_TYPE_DEVICE)
static void
gdk_quartz_device_core_class_init (GdkQuartzDeviceCoreClass *klass)
{
GdkDeviceClass *device_class = GDK_DEVICE_CLASS (klass);
device_class->get_history = gdk_quartz_device_core_get_history;
device_class->get_state = gdk_quartz_device_core_get_state;
device_class->set_surface_cursor = gdk_quartz_device_core_set_surface_cursor;
device_class->warp = gdk_quartz_device_core_warp;
device_class->query_state = gdk_quartz_device_core_query_state;
device_class->grab = gdk_quartz_device_core_grab;
device_class->ungrab = gdk_quartz_device_core_ungrab;
device_class->surface_at_position = gdk_quartz_device_core_surface_at_position;
}
static void
gdk_quartz_device_core_init (GdkQuartzDeviceCore *quartz_device_core)
{
GdkDevice *device;
device = GDK_DEVICE (quartz_device_core);
_gdk_device_add_axis (device, NULL, GDK_AXIS_X, 0, 0, 1);
_gdk_device_add_axis (device, NULL, GDK_AXIS_Y, 0, 0, 1);
}
static gboolean
gdk_quartz_device_core_get_history (GdkDevice *device,
GdkSurface *window,
guint32 start,
guint32 stop,
GdkTimeCoord ***events,
gint *n_events)
{
return FALSE;
}
static void
gdk_quartz_device_core_get_state (GdkDevice *device,
GdkSurface *window,
gdouble *axes,
GdkModifierType *mask)
{
gdouble x_pos, y_pos;
gdk_surface_get_device_position (window, device, &x_pos, &y_pos, mask);
if (axes)
{
axes[0] = x_pos;
axes[1] = y_pos;
}
}
static void
translate_coords_to_child_coords (GdkSurface *parent,
GdkSurface *child,
gint *x,
gint *y)
{
GdkSurface *current = child;
if (child == parent)
return;
while (current != parent)
{
gint tmp_x, tmp_y;
gdk_surface_get_origin (current, &tmp_x, &tmp_y);
*x -= tmp_x;
*y -= tmp_y;
current = gdk_surface_get_parent (current);
}
}
static void
gdk_quartz_device_core_set_surface_cursor (GdkDevice *device,
GdkSurface *window,
GdkCursor *cursor)
{
NSCursor *nscursor;
if (GDK_SURFACE_DESTROYED (window))
return;
nscursor = _gdk_quartz_cursor_get_ns_cursor (cursor);
[nscursor set];
}
static void
gdk_quartz_device_core_warp (GdkDevice *device,
gdouble x,
gdouble y)
{
CGDisplayMoveCursorToPoint (CGMainDisplayID (), CGPointMake (x, y));
}
static GdkSurface *
gdk_quartz_device_core_query_state_helper (GdkSurface *window,
GdkDevice *device,
gdouble *x,
gdouble *y,
GdkModifierType *mask)
{
GdkSurface *toplevel;
NSPoint point;
gint x_tmp, y_tmp;
GdkSurface *found_window;
g_return_val_if_fail (window == NULL || GDK_IS_SURFACE (window), NULL);
if (GDK_SURFACE_DESTROYED (window))
{
*x = 0;
*y = 0;
*mask = 0;
return NULL;
}
toplevel = gdk_surface_get_toplevel (window);
if (mask)
*mask = _gdk_quartz_events_get_current_keyboard_modifiers () |
_gdk_quartz_events_get_current_mouse_modifiers ();
/* Get the y coordinate, needs to be flipped. */
if (window == _gdk_root)
{
point = [NSEvent mouseLocation];
_gdk_quartz_surface_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
}
else
{
GdkSurfaceImplQuartz *impl;
NSWindow *nswindow;
impl = GDK_SURFACE_IMPL_QUARTZ (toplevel->impl);
nswindow = impl->toplevel;
point = [nswindow mouseLocationOutsideOfEventStream];
x_tmp = point.x;
y_tmp = toplevel->height - point.y;
window = toplevel;
}
found_window = _gdk_quartz_surface_find_child (window, x_tmp, y_tmp,
FALSE);
if (found_window == _gdk_root)
found_window = NULL;
else if (found_window)
translate_coords_to_child_coords (window, found_window,
&x_tmp, &y_tmp);
if (x)
*x = x_tmp;
if (y)
*y = y_tmp;
return found_window;
}
static void
gdk_quartz_device_core_query_state (GdkDevice *device,
GdkSurface *window,
GdkSurface **child_window,
gdouble *root_x,
gdouble *root_y,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask)
{
GdkSurface *found_window;
NSPoint point;
gint x_tmp, y_tmp;
if (window == NULL)
window = _gdk_root;
found_window = gdk_quartz_device_core_query_state_helper (window, device,
win_x, win_y,
mask);
if (root_window)
*root_window = _gdk_root;
if (child_window)
*child_window = found_window;
point = [NSEvent mouseLocation];
_gdk_quartz_surface_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
if (root_x)
*root_x = x_tmp;
if (root_y)
*root_y = y_tmp;
}
static GdkGrabStatus
gdk_quartz_device_core_grab (GdkDevice *device,
GdkSurface *window,
gboolean owner_events,
GdkEventMask event_mask,
GdkSurface *confine_to,
GdkCursor *cursor,
guint32 time_)
{
/* Should remain empty */
return GDK_GRAB_SUCCESS;
}
static void
gdk_quartz_device_core_ungrab (GdkDevice *device,
guint32 time_)
{
GdkDeviceGrabInfo *grab;
grab = _gdk_display_get_last_device_grab (_gdk_display, device);
if (grab)
grab->serial_end = 0;
_gdk_display_device_grab_update (_gdk_display, device, NULL, 0);
}
static GdkSurface *
gdk_quartz_device_core_surface_at_position (GdkDevice *device,
gdouble *win_x,
gdouble *win_y,
GdkModifierType *mask,
gboolean get_toplevel)
{
GdkSurface *found_window;
NSPoint point;
gint x_tmp, y_tmp;
/* Get mouse coordinates, find window under the mouse pointer */
point = [NSEvent mouseLocation];
_gdk_quartz_surface_nspoint_to_gdk_xy (point, &x_tmp, &y_tmp);
found_window = _gdk_quartz_surface_find_child (_gdk_root, x_tmp, y_tmp, get_toplevel);
if (found_window)
translate_coords_to_child_coords (_gdk_root, found_window, &x_tmp, &y_tmp);
if (win_x)
*win_x = found_window ? x_tmp : -1;
if (win_y)
*win_y = found_window ? y_tmp : -1;
if (mask)
*mask = _gdk_quartz_events_get_current_keyboard_modifiers () |
_gdk_quartz_events_get_current_mouse_modifiers ();
return found_window;
}

View File

@ -1,119 +0,0 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gdk/gdktypes.h>
#include <gdk/gdkdevicemanager.h>
#include <gdk/gdkdeviceprivate.h>
#include <gdk/gdkseatdefaultprivate.h>
#include <gdk/gdkdevicemanagerprivate.h>
#include "gdkdevicemanager-core-quartz.h"
#include "gdkquartzdevice-core.h"
#include "gdkkeysyms.h"
#include "gdkprivate-quartz.h"
#define HAS_FOCUS(toplevel) \
((toplevel)->has_focus || (toplevel)->has_pointer_focus)
static void gdk_quartz_device_manager_core_finalize (GObject *object);
static void gdk_quartz_device_manager_core_constructed (GObject *object);
static GdkDevice * gdk_quartz_device_manager_core_get_client_pointer (GdkDeviceManager *device_manager);
G_DEFINE_TYPE (GdkQuartzDeviceManagerCore, gdk_quartz_device_manager_core, G_TYPE_OBJECT)
static void
gdk_quartz_device_manager_core_class_init (GdkQuartzDeviceManagerCoreClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gdk_quartz_device_manager_core_finalize;
object_class->constructed = gdk_quartz_device_manager_core_constructed;
}
static GdkDevice *
create_core_pointer (GdkQuartzDeviceManagerCore *device_manager,
GdkDisplay *display)
{
return g_object_new (GDK_TYPE_QUARTZ_DEVICE_CORE,
"name", "Core Pointer",
"type", GDK_DEVICE_TYPE_LOGICAL,
"input-source", GDK_SOURCE_MOUSE,
"input-mode", GDK_MODE_SCREEN,
"has-cursor", TRUE,
"display", display,
"device-manager", device_manager,
NULL);
}
static GdkDevice *
create_core_keyboard (GdkQuartzDeviceManagerCore *device_manager,
GdkDisplay *display)
{
return g_object_new (GDK_TYPE_QUARTZ_DEVICE_CORE,
"name", "Core Keyboard",
"type", GDK_DEVICE_TYPE_LOGICAL,
"input-source", GDK_SOURCE_KEYBOARD,
"input-mode", GDK_MODE_SCREEN,
"has-cursor", FALSE,
"display", display,
"device-manager", device_manager,
NULL);
}
static void
gdk_quartz_device_manager_core_init (GdkQuartzDeviceManagerCore *device_manager)
{
}
static void
gdk_quartz_device_manager_core_finalize (GObject *object)
{
GdkQuartzDeviceManagerCore *quartz_device_manager_core;
quartz_device_manager_core = GDK_QUARTZ_DEVICE_MANAGER_CORE (object);
g_object_unref (quartz_device_manager_core->core_pointer);
g_object_unref (quartz_device_manager_core->core_keyboard);
G_OBJECT_CLASS (gdk_quartz_device_manager_core_parent_class)->finalize (object);
}
static void
gdk_quartz_device_manager_core_constructed (GObject *object)
{
GdkQuartzDeviceManagerCore *device_manager;
GdkDisplay *display;
GdkSeat *seat;
display = _gdk_display;
device_manager = GDK_QUARTZ_DEVICE_MANAGER_CORE (object);
device_manager->core_pointer = create_core_pointer (GDK_DEVICE_MANAGER (device_manager), display);
device_manager->core_keyboard = create_core_keyboard (GDK_DEVICE_MANAGER (device_manager), display);
_gdk_device_set_associated_device (device_manager->core_pointer, device_manager->core_keyboard);
_gdk_device_set_associated_device (device_manager->core_keyboard, device_manager->core_pointer);
seat = gdk_seat_default_new_for_logical_pair (device_manager->core_pointer,
device_manager->core_keyboard);
gdk_display_add_seat (display, seat);
g_object_unref (seat);
}

View File

@ -1,243 +0,0 @@
/* gdkdisplay-quartz.c
*
* Copyright (C) 2005 Imendio AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gdk/gdk.h>
#include <gdk/gdkdisplayprivate.h>
#include "gdkprivate-quartz.h"
#include "gdkquartzscreen.h"
#include "gdkquartzsurface.h"
#include "gdkquartzdisplay.h"
#include "gdkquartzdevicemanager-core.h"
#include "gdkmonitorprivate.h"
#include "gdkdisplay-quartz.h"
#include "gdkcairocontext-quartz.h"
static GdkSurface *
gdk_quartz_display_get_default_group (GdkDisplay *display)
{
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
/* FIXME: Implement */
return NULL;
}
GdkDeviceManager *
_gdk_device_manager_new (GdkDisplay *display)
{
return g_object_new (GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE,
"display", display,
NULL);
}
GdkDisplay *
_gdk_quartz_display_open (const gchar *display_name)
{
if (_gdk_display != NULL)
return NULL;
_gdk_display = g_object_new (gdk_quartz_display_get_type (), NULL);
_gdk_device_manager = _gdk_device_manager_new (_gdk_display);
_gdk_screen = g_object_new (gdk_quartz_screen_get_type (), NULL);
_gdk_quartz_surface_init_windowing (_gdk_display);
_gdk_quartz_events_init ();
/* Initialize application */
[NSApplication sharedApplication];
#if 0
/* FIXME: Remove the #if 0 when we have these functions */
_gdk_quartz_dnd_init ();
#endif
g_signal_emit_by_name (_gdk_display, "opened");
return _gdk_display;
}
static const gchar *
gdk_quartz_display_get_name (GdkDisplay *display)
{
static gchar *display_name = NULL;
if (!display_name)
{
GDK_QUARTZ_ALLOC_POOL;
display_name = g_strdup ([[[NSHost currentHost] name] UTF8String]);
GDK_QUARTZ_RELEASE_POOL;
}
return display_name;
}
static void
gdk_quartz_display_beep (GdkDisplay *display)
{
g_return_if_fail (GDK_IS_DISPLAY (display));
NSBeep();
}
static void
gdk_quartz_display_sync (GdkDisplay *display)
{
/* Not supported. */
}
static void
gdk_quartz_display_flush (GdkDisplay *display)
{
/* Not supported. */
}
static gboolean
gdk_quartz_display_supports_shapes (GdkDisplay *display)
{
/* FIXME: Implement */
return FALSE;
}
static gboolean
gdk_quartz_display_supports_input_shapes (GdkDisplay *display)
{
/* FIXME: Implement */
return FALSE;
}
static gulong
gdk_quartz_display_get_next_serial (GdkDisplay *display)
{
return 0;
}
static void
gdk_quartz_display_notify_startup_complete (GdkDisplay *display,
const gchar *startup_id)
{
/* FIXME: Implement? */
}
static int
gdk_quartz_display_get_n_monitors (GdkDisplay *display)
{
GdkQuartzDisplay *quartz_display = GDK_QUARTZ_DISPLAY (display);
return quartz_display->monitors->len;
}
static GdkMonitor *
gdk_quartz_display_get_monitor (GdkDisplay *display,
int monitor_num)
{
GdkQuartzDisplay *quartz_display = GDK_QUARTZ_DISPLAY (display);
if (0 <= monitor_num || monitor_num < quartz_display->monitors->len)
return (GdkMonitor *)quartz_display->monitors->pdata[monitor_num];
return NULL;
}
static gboolean
gdk_quartz_display_get_setting (GdkDisplay *display,
const gchar *name,
GValue *value)
{
return _gdk_quartz_get_setting (name, value);
}
G_DEFINE_TYPE (GdkQuartzDisplay, gdk_quartz_display, GDK_TYPE_DISPLAY)
static void
gdk_quartz_display_init (GdkQuartzDisplay *display)
{
GDK_QUARTZ_ALLOC_POOL;
display->monitors = g_ptr_array_new_with_free_func (g_object_unref);
GDK_QUARTZ_RELEASE_POOL;
}
static void
gdk_quartz_display_dispose (GObject *object)
{
GdkQuartzDisplay *display_quartz = GDK_QUARTZ_DISPLAY (object);
g_ptr_array_free (display_quartz->monitors, TRUE);
G_OBJECT_CLASS (gdk_quartz_display_parent_class)->dispose (object);
}
static void
gdk_quartz_display_finalize (GObject *object)
{
GdkQuartzDisplay *display_quartz = GDK_QUARTZ_DISPLAY (object);
G_OBJECT_CLASS (gdk_quartz_display_parent_class)->finalize (object);
}
static void
gdk_quartz_display_class_init (GdkQuartzDisplayClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GdkDisplayClass *display_class = GDK_DISPLAY_CLASS (class);
object_class->finalize = gdk_quartz_display_finalize;
object_class->dispose = gdk_quartz_display_dispose;
display_class->surface_type = GDK_TYPE_QUARTZ_SURFACE;
display_class->cairo_context_type = GDK_TYPE_QUARTZ_CAIRO_CONTEXT;
display_class->get_name = gdk_quartz_display_get_name;
display_class->beep = gdk_quartz_display_beep;
display_class->sync = gdk_quartz_display_sync;
display_class->flush = gdk_quartz_display_flush;
display_class->queue_events = _gdk_quartz_display_queue_events;
display_class->has_pending = _gdk_quartz_display_has_pending;
display_class->get_default_group = gdk_quartz_display_get_default_group;
display_class->supports_shapes = gdk_quartz_display_supports_shapes;
display_class->supports_input_shapes = gdk_quartz_display_supports_input_shapes;
display_class->get_default_cursor_size = _gdk_quartz_display_get_default_cursor_size;
display_class->get_maximal_cursor_size = _gdk_quartz_display_get_maximal_cursor_size;
display_class->supports_cursor_alpha = _gdk_quartz_display_supports_cursor_alpha;
display_class->supports_cursor_color = _gdk_quartz_display_supports_cursor_color;
display_class->get_next_serial = gdk_quartz_display_get_next_serial;
display_class->notify_startup_complete = gdk_quartz_display_notify_startup_complete;
display_class->event_data_copy = _gdk_quartz_display_event_data_copy;
display_class->event_data_free = _gdk_quartz_display_event_data_free;
display_class->create_surface_impl = _gdk_quartz_display_create_surface_impl;
display_class->get_keymap = _gdk_quartz_display_get_keymap;
display_class->get_n_monitors = gdk_quartz_display_get_n_monitors;
display_class->get_monitor = gdk_quartz_display_get_monitor;
display_class->get_setting = gdk_quartz_display_get_setting;
ProcessSerialNumber psn = { 0, kCurrentProcess };
/* Make the current process a foreground application, i.e. an app
* with a user interface, in case we're not running from a .app bundle
*/
TransformProcessType (&psn, kProcessTransformToForegroundApplication);
}

View File

@ -1,77 +0,0 @@
/*
* gdkdisplay-quartz.h
*
* Copyright 2017 Tom Schoonjans
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_DISPLAY__
#define __GDK_QUARTZ_DISPLAY__
#include "gdkdisplayprivate.h"
#include "gdkkeys.h"
#include "gdksurface.h"
#include "gdkinternals.h"
G_BEGIN_DECLS
struct _GdkQuartzDisplay
{
GdkDisplay parent_instance;
GPtrArray *monitors;
};
struct _GdkQuartzDisplayClass
{
GdkDisplayClass parent_class;
};
/* Display methods - events */
void _gdk_quartz_display_queue_events (GdkDisplay *display);
gboolean _gdk_quartz_display_has_pending (GdkDisplay *display);
void _gdk_quartz_display_event_data_copy (GdkDisplay *display,
const GdkEvent *src,
GdkEvent *dst);
void _gdk_quartz_display_event_data_free (GdkDisplay *display,
GdkEvent *event);
/* Display methods - cursor */
gboolean _gdk_quartz_display_supports_cursor_alpha (GdkDisplay *display);
gboolean _gdk_quartz_display_supports_cursor_color (GdkDisplay *display);
void _gdk_quartz_display_get_default_cursor_size (GdkDisplay *display,
guint *width,
guint *height);
void _gdk_quartz_display_get_maximal_cursor_size (GdkDisplay *display,
guint *width,
guint *height);
/* Display methods - window */
void _gdk_quartz_display_before_process_all_updates (GdkDisplay *display);
void _gdk_quartz_display_after_process_all_updates (GdkDisplay *display);
void _gdk_quartz_display_create_surface_impl (GdkDisplay *display,
GdkSurface *window,
GdkSurface *real_parent,
GdkSurfaceAttr *attributes);
/* Display methods - keymap */
GdkKeymap * _gdk_quartz_display_get_keymap (GdkDisplay *display);
G_END_DECLS
#endif /* __GDK_QUARTZ_DISPLAY__ */

View File

@ -1,61 +0,0 @@
/* GDK - The GIMP Drawing Kit
* gdkdisplaymanager-quartz.c
*
* Copyright (C) 2005 Imendio AB
* Copyright 2010 Red Hat, Inc.
*
* Author: Matthias clasen
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <ApplicationServices/ApplicationServices.h>
#include "gdkquartzdisplay.h"
#include "gdkquartzdisplaymanager.h"
#include "gdkprivate-quartz.h"
#include "gdkdisplaymanagerprivate.h"
#include "gdkinternals.h"
struct _GdkQuartzDisplayManager
{
GdkDisplayManager parent;
};
G_DEFINE_TYPE (GdkQuartzDisplayManager, gdk_quartz_display_manager, GDK_TYPE_DISPLAY_MANAGER)
static void
gdk_quartz_display_manager_init (GdkQuartzDisplayManager *manager)
{
}
static void
gdk_quartz_display_manager_finalize (GObject *object)
{
g_error ("A GdkQuartzDisplayManager object was finalized. This should not happen");
G_OBJECT_CLASS (gdk_quartz_display_manager_parent_class)->finalize (object);
}
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;
}

View File

@ -1,99 +0,0 @@
/* gdkdnd-quartz.c
*
* Copyright (C) 2005 Imendio AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkdnd.h"
#include "gdkquartzdnd.h"
#include "gdkprivate-quartz.h"
G_DEFINE_TYPE (GdkQuartzDragContext, gdk_quartz_drag_context, GDK_TYPE_DRAG_CONTEXT)
GdkDragContext *_gdk_quartz_drag_source_context = NULL;
GdkDragContext *
gdk_quartz_drag_source_context_libgtk_only ()
{
return _gdk_quartz_drag_source_context;
}
GdkDragContext *
_gdk_quartz_surface_drag_begin (GdkSurface *window,
GdkDevice *device,
GList *targets,
gint dx,
gint dy)
{
g_assert (_gdk_quartz_drag_source_context == NULL);
/* Create fake context */
_gdk_quartz_drag_source_context = g_object_new (GDK_TYPE_QUARTZ_DRAG_CONTEXT,
"device", device,
NULL);
_gdk_quartz_drag_source_context->source_surface = window;
g_object_ref (window);
_gdk_quartz_drag_source_context->targets = targets;
return _gdk_quartz_drag_source_context;
}
static void
gdk_quartz_drag_context_drag_drop (GdkDragContext *context,
guint32 time)
{
/* FIXME: Implement */
}
static void
gdk_quartz_drag_context_drag_abort (GdkDragContext *context,
guint32 time)
{
/* FIXME: Implement */
}
id
gdk_quartz_drag_context_get_dragging_info_libgtk_only (GdkDragContext *context)
{
return GDK_QUARTZ_DRAG_CONTEXT (context)->dragging_info;
}
static void
gdk_quartz_drag_context_init (GdkQuartzDragContext *context)
{
}
static void
gdk_quartz_drag_context_finalize (GObject *object)
{
G_OBJECT_CLASS (gdk_quartz_drag_context_parent_class)->finalize (object);
}
static void
gdk_quartz_drag_context_class_init (GdkQuartzDragContextClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkDragContextClass *context_class = GDK_DRAG_CONTEXT_CLASS (klass);
object_class->finalize = gdk_quartz_drag_context_finalize;
context_class->drag_abort = gdk_quartz_drag_context_drag_abort;
context_class->drag_drop = gdk_quartz_drag_context_drag_drop;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +0,0 @@
/* GDK - The GIMP Drawing Kit
*
* gdkglcontext-quartz.c: Quartz specific OpenGL wrappers
*
* Copyright © 2014 Emmanuele Bassi
* Copyright © 2014 Alexander Larsson
* Copyright © 2014 Brion Vibber
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkglcontext-quartz.h"
#include "gdkintl.h"
GdkGLContext *
gdk_quartz_surface_create_gl_context (GdkSurface *window,
gboolean attached,
GdkGLContext *share,
GError **error)
{
/* FIXME: implement */
g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
_("Not implemented on OS X"));
return NULL;
}

View File

@ -1,39 +0,0 @@
/* GDK - The GIMP Drawing Kit
*
* gdkglcontext-quartz.h: Private Quartz specific OpenGL wrappers
*
* Copyright © 2014 Emmanuele Bassi
* Copyright © 2014 Red Hat, Int
* Copyright © 2014 Brion Vibber
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_GL_CONTEXT__
#define __GDK_QUARTZ_GL_CONTEXT__
#include "gdkglcontextprivate.h"
#include "gdksurface.h"
#include "gdkinternals.h"
G_BEGIN_DECLS
GdkGLContext * gdk_quartz_surface_create_gl_context (GdkSurface *window,
gboolean attach,
GdkGLContext *share,
GError **error);
G_END_DECLS
#endif /* __GDK_QUARTZ_GL_CONTEXT__ */

View File

@ -1,47 +0,0 @@
/* gdkglobals-quartz.c
*
* Copyright (C) 2005 Imendio AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdktypes.h"
#include "gdkquartz.h"
#include "gdkscreen-quartz.h"
GdkDisplay *_gdk_display = NULL;
GdkQuartzScreen *_gdk_screen = NULL;
GdkSurface *_gdk_root = NULL;
GdkDeviceManager *_gdk_device_manager = NULL;
GdkOSXVersion
gdk_quartz_osx_version (void)
{
static gint32 minor = GDK_OSX_UNSUPPORTED;
if (minor == GDK_OSX_UNSUPPORTED)
{
OSErr err = Gestalt (gestaltSystemVersionMinor, (SInt32*)&minor);
g_return_val_if_fail (err == noErr, GDK_OSX_UNSUPPORTED);
}
if (minor < GDK_OSX_MIN)
return GDK_OSX_UNSUPPORTED;
else if (minor > GDK_OSX_CURRENT)
return GDK_OSX_NEW;
else
return minor;
}

View File

@ -1,850 +0,0 @@
/* gdkkeys-quartz.c
*
* Copyright (C) 2000 Red Hat, Inc.
* Copyright (C) 2005 Imendio AB
*
* 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/>.
*/
/* Some parts of this code come from quartzKeyboard.c,
* from the Apple X11 Server.
*
* Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
* HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name(s) of the above
* copyright holders shall not be used in advertising or otherwise to
* promote the sale, use or other dealings in this Software without
* prior written authorization.
*/
#include "config.h"
#include <Carbon/Carbon.h>
#include <AppKit/NSEvent.h>
#include "gdk.h"
#include "gdkquartzkeys.h"
#include "gdkkeysprivate.h"
#include "gdkkeysyms.h"
#define NUM_KEYCODES 128
#define KEYVALS_PER_KEYCODE 4
static GdkKeymap *default_keymap = NULL;
struct _GdkQuartzKeymap
{
GdkKeymap keymap;
};
struct _GdkQuartzKeymapClass
{
GdkKeymapClass keymap_class;
};
G_DEFINE_TYPE (GdkQuartzKeymap, gdk_quartz_keymap, GDK_TYPE_KEYMAP)
GdkKeymap *
_gdk_quartz_display_get_keymap (GdkDisplay *display)
{
if (default_keymap == NULL)
default_keymap = g_object_new (gdk_quartz_keymap_get_type (), NULL);
return default_keymap;
}
/* This is a table of all keyvals. Each keycode gets KEYVALS_PER_KEYCODE entries.
* TThere is 1 keyval per modifier (Nothing, Shift, Alt, Shift+Alt);
*/
static guint *keyval_array = NULL;
static inline UniChar
macroman2ucs (unsigned char c)
{
/* Precalculated table mapping MacRoman-128 to Unicode. Generated
by creating single element CFStringRefs then extracting the
first character. */
static const unsigned short table[128] = {
0xc4, 0xc5, 0xc7, 0xc9, 0xd1, 0xd6, 0xdc, 0xe1,
0xe0, 0xe2, 0xe4, 0xe3, 0xe5, 0xe7, 0xe9, 0xe8,
0xea, 0xeb, 0xed, 0xec, 0xee, 0xef, 0xf1, 0xf3,
0xf2, 0xf4, 0xf6, 0xf5, 0xfa, 0xf9, 0xfb, 0xfc,
0x2020, 0xb0, 0xa2, 0xa3, 0xa7, 0x2022, 0xb6, 0xdf,
0xae, 0xa9, 0x2122, 0xb4, 0xa8, 0x2260, 0xc6, 0xd8,
0x221e, 0xb1, 0x2264, 0x2265, 0xa5, 0xb5, 0x2202, 0x2211,
0x220f, 0x3c0, 0x222b, 0xaa, 0xba, 0x3a9, 0xe6, 0xf8,
0xbf, 0xa1, 0xac, 0x221a, 0x192, 0x2248, 0x2206, 0xab,
0xbb, 0x2026, 0xa0, 0xc0, 0xc3, 0xd5, 0x152, 0x153,
0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0xf7, 0x25ca,
0xff, 0x178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
0x2021, 0xb7, 0x201a, 0x201e, 0x2030, 0xc2, 0xca, 0xc1,
0xcb, 0xc8, 0xcd, 0xce, 0xcf, 0xcc, 0xd3, 0xd4,
0xf8ff, 0xd2, 0xda, 0xdb, 0xd9, 0x131, 0x2c6, 0x2dc,
0xaf, 0x2d8, 0x2d9, 0x2da, 0xb8, 0x2dd, 0x2db, 0x2c7
};
if (c < 128)
return c;
else
return table[c - 128];
}
const static struct {
guint keycode;
guint keyval;
unsigned int modmask; /* So we can tell when a mod key is pressed/released */
} modifier_keys[] = {
{ 54, GDK_KEY_Meta_R, NSCommandKeyMask },
{ 55, GDK_KEY_Meta_L, NSCommandKeyMask },
{ 56, GDK_KEY_Shift_L, NSShiftKeyMask },
{ 57, GDK_KEY_Caps_Lock, NSAlphaShiftKeyMask },
{ 58, GDK_KEY_Alt_L, NSAlternateKeyMask },
{ 59, GDK_KEY_Control_L, NSControlKeyMask },
{ 60, GDK_KEY_Shift_R, NSShiftKeyMask },
{ 61, GDK_KEY_Alt_R, NSAlternateKeyMask },
{ 62, GDK_KEY_Control_R, NSControlKeyMask }
};
const static struct {
guint keycode;
guint keyval;
} function_keys[] = {
{ 122, GDK_KEY_F1 },
{ 120, GDK_KEY_F2 },
{ 99, GDK_KEY_F3 },
{ 118, GDK_KEY_F4 },
{ 96, GDK_KEY_F5 },
{ 97, GDK_KEY_F6 },
{ 98, GDK_KEY_F7 },
{ 100, GDK_KEY_F8 },
{ 101, GDK_KEY_F9 },
{ 109, GDK_KEY_F10 },
{ 103, GDK_KEY_F11 },
{ 111, GDK_KEY_F12 },
{ 105, GDK_KEY_F13 },
{ 107, GDK_KEY_F14 },
{ 113, GDK_KEY_F15 },
{ 106, GDK_KEY_F16 }
};
const static struct {
guint keycode;
guint normal_keyval, keypad_keyval;
} known_numeric_keys[] = {
{ 65, GDK_KEY_period, GDK_KEY_KP_Decimal },
{ 67, GDK_KEY_asterisk, GDK_KEY_KP_Multiply },
{ 69, GDK_KEY_plus, GDK_KEY_KP_Add },
{ 75, GDK_KEY_slash, GDK_KEY_KP_Divide },
{ 76, GDK_KEY_Return, GDK_KEY_KP_Enter },
{ 78, GDK_KEY_minus, GDK_KEY_KP_Subtract },
{ 81, GDK_KEY_equal, GDK_KEY_KP_Equal },
{ 82, GDK_KEY_0, GDK_KEY_KP_0 },
{ 83, GDK_KEY_1, GDK_KEY_KP_1 },
{ 84, GDK_KEY_2, GDK_KEY_KP_2 },
{ 85, GDK_KEY_3, GDK_KEY_KP_3 },
{ 86, GDK_KEY_4, GDK_KEY_KP_4 },
{ 87, GDK_KEY_5, GDK_KEY_KP_5 },
{ 88, GDK_KEY_6, GDK_KEY_KP_6 },
{ 89, GDK_KEY_7, GDK_KEY_KP_7 },
{ 91, GDK_KEY_8, GDK_KEY_KP_8 },
{ 92, GDK_KEY_9, GDK_KEY_KP_9 }
};
/* These values aren't covered by gdk_unicode_to_keyval */
const static struct {
gunichar ucs_value;
guint keyval;
} special_ucs_table [] = {
{ 0x0001, GDK_KEY_Home },
{ 0x0003, GDK_KEY_Return },
{ 0x0004, GDK_KEY_End },
{ 0x0008, GDK_KEY_BackSpace },
{ 0x0009, GDK_KEY_Tab },
{ 0x000b, GDK_KEY_Page_Up },
{ 0x000c, GDK_KEY_Page_Down },
{ 0x000d, GDK_KEY_Return },
{ 0x001b, GDK_KEY_Escape },
{ 0x001c, GDK_KEY_Left },
{ 0x001d, GDK_KEY_Right },
{ 0x001e, GDK_KEY_Up },
{ 0x001f, GDK_KEY_Down },
{ 0x007f, GDK_KEY_Delete },
{ 0xf027, GDK_KEY_dead_acute },
{ 0xf060, GDK_KEY_dead_grave },
{ 0xf300, GDK_KEY_dead_grave },
{ 0xf0b4, GDK_KEY_dead_acute },
{ 0xf301, GDK_KEY_dead_acute },
{ 0xf385, GDK_KEY_dead_acute },
{ 0xf05e, GDK_KEY_dead_circumflex },
{ 0xf2c6, GDK_KEY_dead_circumflex },
{ 0xf302, GDK_KEY_dead_circumflex },
{ 0xf07e, GDK_KEY_dead_tilde },
{ 0xf2dc, GDK_KEY_dead_tilde },
{ 0xf303, GDK_KEY_dead_tilde },
{ 0xf342, GDK_KEY_dead_perispomeni },
{ 0xf0af, GDK_KEY_dead_macron },
{ 0xf304, GDK_KEY_dead_macron },
{ 0xf2d8, GDK_KEY_dead_breve },
{ 0xf306, GDK_KEY_dead_breve },
{ 0xf2d9, GDK_KEY_dead_abovedot },
{ 0xf307, GDK_KEY_dead_abovedot },
{ 0xf0a8, GDK_KEY_dead_diaeresis },
{ 0xf308, GDK_KEY_dead_diaeresis },
{ 0xf2da, GDK_KEY_dead_abovering },
{ 0xf30A, GDK_KEY_dead_abovering },
{ 0xf022, GDK_KEY_dead_doubleacute },
{ 0xf2dd, GDK_KEY_dead_doubleacute },
{ 0xf30B, GDK_KEY_dead_doubleacute },
{ 0xf2c7, GDK_KEY_dead_caron },
{ 0xf30C, GDK_KEY_dead_caron },
{ 0xf0be, GDK_KEY_dead_cedilla },
{ 0xf327, GDK_KEY_dead_cedilla },
{ 0xf2db, GDK_KEY_dead_ogonek },
{ 0xf328, GDK_KEY_dead_ogonek },
{ 0xfe5d, GDK_KEY_dead_iota },
{ 0xf323, GDK_KEY_dead_belowdot },
{ 0xf309, GDK_KEY_dead_hook },
{ 0xf31B, GDK_KEY_dead_horn },
{ 0xf02d, GDK_KEY_dead_stroke },
{ 0xf335, GDK_KEY_dead_stroke },
{ 0xf336, GDK_KEY_dead_stroke },
{ 0xf313, GDK_KEY_dead_abovecomma },
/* { 0xf313, GDK_KEY_dead_psili }, */
{ 0xf314, GDK_KEY_dead_abovereversedcomma },
/* { 0xf314, GDK_KEY_dead_dasia }, */
{ 0xf30F, GDK_KEY_dead_doublegrave },
{ 0xf325, GDK_KEY_dead_belowring },
{ 0xf2cd, GDK_KEY_dead_belowmacron },
{ 0xf331, GDK_KEY_dead_belowmacron },
{ 0xf32D, GDK_KEY_dead_belowcircumflex },
{ 0xf330, GDK_KEY_dead_belowtilde },
{ 0xf32E, GDK_KEY_dead_belowbreve },
{ 0xf324, GDK_KEY_dead_belowdiaeresis },
{ 0xf311, GDK_KEY_dead_invertedbreve },
{ 0xf02c, GDK_KEY_dead_belowcomma },
{ 0xf326, GDK_KEY_dead_belowcomma }
};
static void
update_keymap (void)
{
const void *chr_data = NULL;
guint *p;
int i;
/* Note: we could check only if building against the 10.5 SDK instead, but
* that would make non-xml layouts not work in 32-bit which would be a quite
* bad regression. This way, old unsupported layouts will just not work in
* 64-bit.
*/
#ifdef __LP64__
TISInputSourceRef new_layout = TISCopyCurrentKeyboardLayoutInputSource ();
CFDataRef layout_data_ref;
#else
KeyboardLayoutRef new_layout;
KeyboardLayoutKind layout_kind;
KLGetCurrentKeyboardLayout (&new_layout);
#endif
g_free (keyval_array);
keyval_array = g_new0 (guint, NUM_KEYCODES * KEYVALS_PER_KEYCODE);
#ifdef __LP64__
layout_data_ref = (CFDataRef) TISGetInputSourceProperty
(new_layout, kTISPropertyUnicodeKeyLayoutData);
if (layout_data_ref)
chr_data = CFDataGetBytePtr (layout_data_ref);
if (chr_data == NULL)
{
g_error ("cannot get keyboard layout data");
return;
}
#else
/* Get the layout kind */
KLGetKeyboardLayoutProperty (new_layout, kKLKind, (const void **)&layout_kind);
/* 8-bit-only keyabord layout */
if (layout_kind == kKLKCHRKind)
{
/* Get chr data */
KLGetKeyboardLayoutProperty (new_layout, kKLKCHRData, (const void **)&chr_data);
for (i = 0; i < NUM_KEYCODES; i++)
{
int j;
UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
p = keyval_array + i * KEYVALS_PER_KEYCODE;
for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
{
UInt32 c, state = 0;
UInt16 key_code;
UniChar uc;
key_code = modifiers[j] | i;
c = KeyTranslate (chr_data, key_code, &state);
if (state != 0)
{
UInt32 state2 = 0;
c = KeyTranslate (chr_data, key_code | 128, &state2);
}
if (c != 0 && c != 0x10)
{
int k;
gboolean found = FALSE;
/* FIXME: some keyboard layouts (e.g. Russian) use a
* different 8-bit character set. We should check
* for this. Not a serious problem, because most
* (all?) of these layouts also have a uchr version.
*/
uc = macroman2ucs (c);
for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
{
if (special_ucs_table[k].ucs_value == uc)
{
p[j] = special_ucs_table[k].keyval;
found = TRUE;
break;
}
}
/* Special-case shift-tab since GTK+ expects
* GDK_KEY_ISO_Left_Tab for that.
*/
if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
p[j] = GDK_KEY_ISO_Left_Tab;
if (!found)
p[j] = gdk_unicode_to_keyval (uc);
}
}
if (p[3] == p[2])
p[3] = 0;
if (p[2] == p[1])
p[2] = 0;
if (p[1] == p[0])
p[1] = 0;
if (p[0] == p[2] &&
p[1] == p[3])
p[2] = p[3] = 0;
}
}
/* unicode keyboard layout */
else if (layout_kind == kKLKCHRuchrKind || layout_kind == kKLuchrKind)
{
/* Get chr data */
KLGetKeyboardLayoutProperty (new_layout, kKLuchrData, (const void **)&chr_data);
#endif
for (i = 0; i < NUM_KEYCODES; i++)
{
int j;
UInt32 modifiers[] = {0, shiftKey, optionKey, shiftKey | optionKey};
UniChar chars[4];
UniCharCount nChars;
p = keyval_array + i * KEYVALS_PER_KEYCODE;
for (j = 0; j < KEYVALS_PER_KEYCODE; j++)
{
UInt32 state = 0;
OSStatus err;
UInt16 key_code;
UniChar uc;
key_code = modifiers[j] | i;
err = UCKeyTranslate (chr_data, i, kUCKeyActionDisplay,
(modifiers[j] >> 8) & 0xFF,
LMGetKbdType(),
0,
&state, 4, &nChars, chars);
/* FIXME: Theoretically, we can get multiple UTF-16
* values; we should convert them to proper unicode and
* figure out whether there are really keyboard layouts
* that give us more than one character for one
* keypress.
*/
if (err == noErr && nChars == 1)
{
int k;
gboolean found = FALSE;
/* A few <Shift><Option>keys return two characters,
* the first of which is U+00a0, which isn't
* interesting; so we return the second. More
* sophisticated handling is the job of a
* GtkIMContext.
*
* If state isn't zero, it means that it's a dead
* key of some sort. Some of those are enumerated in
* the special_ucs_table with the high nibble set to
* f to push it into the private use range. Here we
* do the same.
*/
if (state != 0)
chars[nChars - 1] |= 0xf000;
uc = chars[nChars - 1];
for (k = 0; k < G_N_ELEMENTS (special_ucs_table); k++)
{
if (special_ucs_table[k].ucs_value == uc)
{
p[j] = special_ucs_table[k].keyval;
found = TRUE;
break;
}
}
/* Special-case shift-tab since GTK+ expects
* GDK_KEY_ISO_Left_Tab for that.
*/
if (found && p[j] == GDK_KEY_Tab && modifiers[j] == shiftKey)
p[j] = GDK_KEY_ISO_Left_Tab;
if (!found)
p[j] = gdk_unicode_to_keyval (uc);
}
}
if (p[3] == p[2])
p[3] = 0;
if (p[2] == p[1])
p[2] = 0;
if (p[1] == p[0])
p[1] = 0;
if (p[0] == p[2] &&
p[1] == p[3])
p[2] = p[3] = 0;
}
#ifndef __LP64__
}
else
{
g_error ("unknown type of keyboard layout (neither KCHR nor uchr)"
" - not supported right now");
}
#endif
for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
{
p = keyval_array + modifier_keys[i].keycode * KEYVALS_PER_KEYCODE;
if (p[0] == 0 && p[1] == 0 &&
p[2] == 0 && p[3] == 0)
p[0] = modifier_keys[i].keyval;
}
for (i = 0; i < G_N_ELEMENTS (function_keys); i++)
{
p = keyval_array + function_keys[i].keycode * KEYVALS_PER_KEYCODE;
p[0] = function_keys[i].keyval;
p[1] = p[2] = p[3] = 0;
}
for (i = 0; i < G_N_ELEMENTS (known_numeric_keys); i++)
{
p = keyval_array + known_numeric_keys[i].keycode * KEYVALS_PER_KEYCODE;
if (p[0] == known_numeric_keys[i].normal_keyval)
p[0] = known_numeric_keys[i].keypad_keyval;
}
if (default_keymap != NULL)
g_signal_emit_by_name (default_keymap, "keys-changed");
}
static PangoDirection
gdk_quartz_keymap_get_direction (GdkKeymap *keymap)
{
return PANGO_DIRECTION_NEUTRAL;
}
static gboolean
gdk_quartz_keymap_have_bidi_layouts (GdkKeymap *keymap)
{
/* FIXME: Can we implement this? */
return FALSE;
}
static gboolean
gdk_quartz_keymap_get_caps_lock_state (GdkKeymap *keymap)
{
/* FIXME: Implement this. */
return FALSE;
}
static gboolean
gdk_quartz_keymap_get_num_lock_state (GdkKeymap *keymap)
{
/* FIXME: Implement this. */
return FALSE;
}
static gboolean
gdk_quartz_keymap_get_scroll_lock_state (GdkKeymap *keymap)
{
/* FIXME: Implement this. */
return FALSE;
}
static gboolean
gdk_quartz_keymap_get_entries_for_keyval (GdkKeymap *keymap,
guint keyval,
GdkKeymapKey **keys,
gint *n_keys)
{
GArray *keys_array;
int i;
*n_keys = 0;
keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
for (i = 0; i < NUM_KEYCODES * KEYVALS_PER_KEYCODE; i++)
{
GdkKeymapKey key;
if (keyval_array[i] != keyval)
continue;
(*n_keys)++;
key.keycode = i / KEYVALS_PER_KEYCODE;
key.group = (i % KEYVALS_PER_KEYCODE) >= 2;
key.level = i % 2;
g_array_append_val (keys_array, key);
}
*keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
return *n_keys > 0;;
}
static gboolean
gdk_quartz_keymap_get_entries_for_keycode (GdkKeymap *keymap,
guint hardware_keycode,
GdkKeymapKey **keys,
guint **keyvals,
gint *n_entries)
{
GArray *keys_array, *keyvals_array;
int i;
guint *p;
*n_entries = 0;
if (hardware_keycode > NUM_KEYCODES)
return FALSE;
if (keys)
keys_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
else
keys_array = NULL;
if (keyvals)
keyvals_array = g_array_new (FALSE, FALSE, sizeof (guint));
else
keyvals_array = NULL;
p = keyval_array + hardware_keycode * KEYVALS_PER_KEYCODE;
for (i = 0; i < KEYVALS_PER_KEYCODE; i++)
{
if (!p[i])
continue;
(*n_entries)++;
if (keyvals_array)
g_array_append_val (keyvals_array, p[i]);
if (keys_array)
{
GdkKeymapKey key;
key.keycode = hardware_keycode;
key.group = i >= 2;
key.level = i % 2;
g_array_append_val (keys_array, key);
}
}
if (keys)
*keys = (GdkKeymapKey *)g_array_free (keys_array, FALSE);
if (keyvals)
*keyvals = (guint *)g_array_free (keyvals_array, FALSE);
return *n_entries > 0;
}
#define GET_KEYVAL(keycode, group, level) (keyval_array[(keycode * KEYVALS_PER_KEYCODE + group * 2 + level)])
static guint
gdk_quartz_keymap_lookup_key (GdkKeymap *keymap,
const GdkKeymapKey *key)
{
return GET_KEYVAL (key->keycode, key->group, key->level);
}
static guint
translate_keysym (guint hardware_keycode,
gint group,
GdkModifierType state,
gint *effective_group,
gint *effective_level)
{
gint level;
guint tmp_keyval;
level = (state & GDK_SHIFT_MASK) ? 1 : 0;
if (!(GET_KEYVAL (hardware_keycode, group, 0) || GET_KEYVAL (hardware_keycode, group, 1)) &&
(GET_KEYVAL (hardware_keycode, 0, 0) || GET_KEYVAL (hardware_keycode, 0, 1)))
group = 0;
if (!GET_KEYVAL (hardware_keycode, group, level) &&
GET_KEYVAL (hardware_keycode, group, 0))
level = 0;
tmp_keyval = GET_KEYVAL (hardware_keycode, group, level);
if (state & GDK_LOCK_MASK)
{
guint upper = gdk_keyval_to_upper (tmp_keyval);
if (upper != tmp_keyval)
tmp_keyval = upper;
}
if (effective_group)
*effective_group = group;
if (effective_level)
*effective_level = level;
return tmp_keyval;
}
static gboolean
gdk_quartz_keymap_translate_keyboard_state (GdkKeymap *keymap,
guint hardware_keycode,
GdkModifierType state,
gint group,
guint *keyval,
gint *effective_group,
gint *level,
GdkModifierType *consumed_modifiers)
{
guint tmp_keyval;
GdkModifierType bit;
if (keyval)
*keyval = 0;
if (effective_group)
*effective_group = 0;
if (level)
*level = 0;
if (consumed_modifiers)
*consumed_modifiers = 0;
if (hardware_keycode < 0 || hardware_keycode >= NUM_KEYCODES)
return FALSE;
tmp_keyval = translate_keysym (hardware_keycode, group, state, level, effective_group);
/* Check if modifiers modify the keyval */
if (consumed_modifiers)
{
guint tmp_modifiers = (state & GDK_MODIFIER_MASK);
for (bit = 1; bit <= tmp_modifiers; bit <<= 1)
{
if ((bit & tmp_modifiers) &&
translate_keysym (hardware_keycode, group, state & ~bit,
NULL, NULL) == tmp_keyval)
tmp_modifiers &= ~bit;
}
*consumed_modifiers = tmp_modifiers;
}
if (keyval)
*keyval = tmp_keyval;
return TRUE;
}
static void
gdk_quartz_keymap_add_virtual_modifiers (GdkKeymap *keymap,
GdkModifierType *state)
{
if (*state & GDK_MOD2_MASK)
*state |= GDK_META_MASK;
}
static gboolean
gdk_quartz_keymap_map_virtual_modifiers (GdkKeymap *keymap,
GdkModifierType *state)
{
if (*state & GDK_META_MASK)
*state |= GDK_MOD2_MASK;
return TRUE;
}
/* What sort of key event is this? Returns one of
* GDK_KEY_PRESS, GDK_KEY_RELEASE, GDK_NOTHING (should be ignored)
*/
GdkEventType
_gdk_quartz_keys_event_type (NSEvent *event)
{
unsigned short keycode;
unsigned int flags;
int i;
switch ([event type])
{
case NSKeyDown:
return GDK_KEY_PRESS;
case NSKeyUp:
return GDK_KEY_RELEASE;
case NSFlagsChanged:
break;
default:
g_assert_not_reached ();
}
/* For flags-changed events, we have to find the special key that caused the
* event, and see if it's in the modifier mask. */
keycode = [event keyCode];
flags = [event modifierFlags];
for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
{
if (modifier_keys[i].keycode == keycode)
{
if (flags & modifier_keys[i].modmask)
return GDK_KEY_PRESS;
else
return GDK_KEY_RELEASE;
}
}
/* Some keypresses (eg: Expose' activations) seem to trigger flags-changed
* events for no good reason. Ignore them! */
return GDK_NOTHING;
}
gboolean
_gdk_quartz_keys_is_modifier (guint keycode)
{
gint i;
for (i = 0; i < G_N_ELEMENTS (modifier_keys); i++)
{
if (modifier_keys[i].modmask == 0)
break;
if (modifier_keys[i].keycode == keycode)
return TRUE;
}
return FALSE;
}
static void
input_sources_changed_notification (CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
update_keymap ();
}
static void
gdk_quartz_keymap_init (GdkQuartzKeymap *keymap)
{
update_keymap ();
CFNotificationCenterAddObserver (CFNotificationCenterGetDistributedCenter (),
keymap,
input_sources_changed_notification,
CFSTR ("AppleSelectedInputSourcesChangedNotification"),
NULL,
CFNotificationSuspensionBehaviorDeliverImmediately);
}
static void
gdk_quartz_keymap_finalize (GObject *object)
{
CFNotificationCenterRemoveObserver (CFNotificationCenterGetDistributedCenter (),
object,
CFSTR ("AppleSelectedInputSourcesChangedNotification"),
NULL);
G_OBJECT_CLASS (gdk_quartz_keymap_parent_class)->finalize (object);
}
static void
gdk_quartz_keymap_class_init (GdkQuartzKeymapClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GdkKeymapClass *keymap_class = GDK_KEYMAP_CLASS (klass);
object_class->finalize = gdk_quartz_keymap_finalize;
keymap_class->get_direction = gdk_quartz_keymap_get_direction;
keymap_class->have_bidi_layouts = gdk_quartz_keymap_have_bidi_layouts;
keymap_class->get_caps_lock_state = gdk_quartz_keymap_get_caps_lock_state;
keymap_class->get_num_lock_state = gdk_quartz_keymap_get_num_lock_state;
keymap_class->get_scroll_lock_state = gdk_quartz_keymap_get_scroll_lock_state;
keymap_class->get_entries_for_keyval = gdk_quartz_keymap_get_entries_for_keyval;
keymap_class->get_entries_for_keycode = gdk_quartz_keymap_get_entries_for_keycode;
keymap_class->lookup_key = gdk_quartz_keymap_lookup_key;
keymap_class->translate_keyboard_state = gdk_quartz_keymap_translate_keyboard_state;
keymap_class->add_virtual_modifiers = gdk_quartz_keymap_add_virtual_modifiers;
keymap_class->map_virtual_modifiers = gdk_quartz_keymap_map_virtual_modifiers;
}

View File

@ -1,65 +0,0 @@
/*
* Copyright © 2017 Tom Schoonjans
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib.h>
#include <gio/gio.h>
#include "gdkmonitor-quartz.h"
#include "gdkscreen-quartz.h"
G_DEFINE_TYPE (GdkQuartzMonitor, gdk_quartz_monitor, GDK_TYPE_MONITOR)
static void
gdk_quartz_monitor_get_workarea (GdkMonitor *monitor,
GdkRectangle *dest)
{
GdkQuartzScreen *quartz_screen = GDK_QUARTZ_SCREEN(_gdk_screen);
GdkQuartzMonitor *quartz_monitor = GDK_QUARTZ_MONITOR(monitor);
GDK_QUARTZ_ALLOC_POOL;
NSArray *array = [NSScreen screens];
if (quartz_monitor->monitor_num < [array count])
{
NSScreen *screen = [array objectAtIndex:quartz_monitor->monitor_num];
NSRect rect = [screen visibleFrame];
dest->x = rect.origin.x - quartz_screen->min_x;
dest->y = quartz_screen->height - (rect.origin.y + rect.size.height) + quartz_screen->min_y;
dest->width = rect.size.width;
dest->height = rect.size.height;
}
else
*dest = monitor->geometry;
GDK_QUARTZ_RELEASE_POOL;
}
static void
gdk_quartz_monitor_init (GdkQuartzMonitor *monitor)
{
}
static void
gdk_quartz_monitor_class_init (GdkQuartzMonitorClass *class)
{
GDK_MONITOR_CLASS (class)->get_workarea = gdk_quartz_monitor_get_workarea;
}

View File

@ -1,41 +0,0 @@
/*
* Copyright © 2017 Tom Schoonjans
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_MONITOR_PRIVATE_H__
#define __GDK_QUARTZ_MONITOR_PRIVATE_H__
#include <glib.h>
#include <gio/gio.h>
#include "gdkmonitorprivate.h"
#include "gdkquartzmonitor.h"
#include "gdkprivate-quartz.h"
struct _GdkQuartzMonitor
{
GdkMonitor parent;
gint monitor_num;
};
struct _GdkQuartzMonitorClass {
GdkMonitorClass parent_class;
};
#endif

View File

@ -1,149 +0,0 @@
/* gdksurface-quartz.c
*
* Copyright (C) 2005-2007 Imendio AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_PRIVATE_QUARTZ_H__
#define __GDK_PRIVATE_QUARTZ_H__
#define GDK_QUARTZ_ALLOC_POOL NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]
#define GDK_QUARTZ_RELEASE_POOL [pool release]
#include <gdk/quartz/gdkquartz.h>
#include <gdk/quartz/gdkdevicemanager-core-quartz.h>
#include <gdk/quartz/gdkdnd-quartz.h>
#include <gdk/quartz/gdkscreen-quartz.h>
#include <gdk/quartz/gdksurface-quartz.h>
#include <gdk/gdk.h>
#include "gdkinternals.h"
#include "config.h"
extern GdkDisplay *_gdk_display;
extern GdkQuartzScreen *_gdk_screen;
extern GdkSurface *_gdk_root;
extern GdkDeviceManager *_gdk_device_manager;
extern GdkDragContext *_gdk_quartz_drag_source_context;
#define GDK_SURFACE_IS_QUARTZ(win) (GDK_IS_SURFACE_IMPL_QUARTZ (((GdkSurface *)win)->impl))
/* Initialization */
void _gdk_quartz_surface_init_windowing (GdkDisplay *display);
void _gdk_quartz_events_init (void);
void _gdk_quartz_event_loop_init (void);
/* Cursor */
NSCursor *_gdk_quartz_cursor_get_ns_cursor (GdkCursor *cursor);
/* Events */
typedef enum {
GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP
} GdkQuartzEventSubType;
void _gdk_quartz_events_update_focus_window (GdkSurface *new_window,
gboolean got_focus);
void _gdk_quartz_events_send_map_event (GdkSurface *window);
GdkModifierType _gdk_quartz_events_get_current_keyboard_modifiers (void);
GdkModifierType _gdk_quartz_events_get_current_mouse_modifiers (void);
void _gdk_quartz_events_break_all_grabs (guint32 time);
/* Event loop */
gboolean _gdk_quartz_event_loop_check_pending (void);
NSEvent * _gdk_quartz_event_loop_get_pending (void);
void _gdk_quartz_event_loop_release_event (NSEvent *event);
/* Keys */
GdkEventType _gdk_quartz_keys_event_type (NSEvent *event);
gboolean _gdk_quartz_keys_is_modifier (guint keycode);
void _gdk_quartz_synthesize_null_key_event (GdkSurface *window);
/* Drag and Drop */
GdkDragContext * _gdk_quartz_surface_drag_begin (GdkSurface *window,
GdkDevice *device,
GList *targets,
gint x_root,
gint y_root);
/* Display */
GdkDisplay * _gdk_quartz_display_open (const gchar *name);
/* Screen */
GdkQuartzScreen *_gdk_quartz_screen_new (void);
void _gdk_quartz_screen_update_window_sizes (GdkQuartzScreen *screen);
/* Screen methods - events */
gboolean _gdk_quartz_get_setting (const gchar *name,
GValue *value);
/* Window */
gboolean _gdk_quartz_surface_is_ancestor (GdkSurface *ancestor,
GdkSurface *window);
void _gdk_quartz_surface_gdk_xy_to_xy (gint gdk_x,
gint gdk_y,
gint *ns_x,
gint *ns_y);
void _gdk_quartz_surface_xy_to_gdk_xy (gint ns_x,
gint ns_y,
gint *gdk_x,
gint *gdk_y);
void _gdk_quartz_surface_nspoint_to_gdk_xy (NSPoint point,
gint *x,
gint *y);
GdkSurface *_gdk_quartz_surface_find_child (GdkSurface *window,
gint x,
gint y,
gboolean get_toplevel);
void _gdk_quartz_surface_attach_to_parent (GdkSurface *window);
void _gdk_quartz_surface_detach_from_parent (GdkSurface *window);
void _gdk_quartz_surface_did_become_main (GdkSurface *window);
void _gdk_quartz_surface_did_resign_main (GdkSurface *window);
void _gdk_quartz_surface_debug_highlight (GdkSurface *window,
gint number);
void _gdk_quartz_surface_update_position (GdkSurface *window);
void _gdk_quartz_surface_update_fullscreen_state (GdkSurface *window);
/* Window methods - property */
gboolean _gdk_quartz_surface_get_property (GdkSurface *window,
GdkAtom property,
GdkAtom type,
gulong offset,
gulong length,
gint pdelete,
GdkAtom *actual_property_type,
gint *actual_format_type,
gint *actual_length,
guchar **data);
void _gdk_quartz_surface_change_property (GdkSurface *window,
GdkAtom property,
GdkAtom type,
gint format,
GdkPropMode mode,
const guchar *data,
gint nelements);
void _gdk_quartz_surface_delete_property (GdkSurface *window,
GdkAtom property);
#endif /* __GDK_PRIVATE_QUARTZ_H__ */

View File

@ -1,89 +0,0 @@
/* gdkquartz.h
*
* Copyright (C) 2005-2007 Imendio AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_H__
#define __GDK_QUARTZ_H__
#include <AppKit/AppKit.h>
#include <gdk/gdk.h>
G_BEGIN_DECLS
/* NSInteger only exists in Leopard and newer. This check has to be
* done after inclusion of the system headers. If NSInteger has not
* been defined, we know for sure that we are on 32-bit.
*/
#ifndef NSINTEGER_DEFINED
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
#ifndef CGFLOAT_DEFINED
typedef float CGFloat;
#endif
typedef enum
{
GDK_OSX_UNSUPPORTED = 0,
GDK_OSX_MIN = 4,
GDK_OSX_TIGER = 4,
GDK_OSX_LEOPARD = 5,
GDK_OSX_SNOW_LEOPARD = 6,
GDK_OSX_LION = 7,
GDK_OSX_MOUNTAIN_LION = 8,
GDK_OSX_MAVERICKS = 9,
GDK_OSX_YOSEMITE = 10,
GDK_OSX_EL_CAPITAN = 11,
GDK_OSX_SIERRA = 12,
GDK_OSX_HIGH_SIERRA = 13,
GDK_OSX_MOJAVE = 14,
GDK_OSX_CURRENT = 14,
GDK_OSX_NEW = 99
} GdkOSXVersion;
GDK_AVAILABLE_IN_ALL
GdkOSXVersion gdk_quartz_osx_version (void);
GDK_AVAILABLE_IN_ALL
GdkAtom gdk_quartz_pasteboard_type_to_atom_libgtk_only (NSString *type);
GDK_AVAILABLE_IN_ALL
NSString *gdk_quartz_target_to_pasteboard_type_libgtk_only (const gchar *target);
GDK_AVAILABLE_IN_ALL
NSString *gdk_quartz_atom_to_pasteboard_type_libgtk_only (GdkAtom atom);
G_END_DECLS
#define __GDKQUARTZ_H_INSIDE__
#include <gdk/quartz/gdkquartzcursor.h>
#include <gdk/quartz/gdkquartzdevice-core.h>
#include <gdk/quartz/gdkquartzdevicemanager-core.h>
#include <gdk/quartz/gdkquartzdisplay.h>
#include <gdk/quartz/gdkquartzdisplaymanager.h>
#include <gdk/quartz/gdkquartzdnd.h>
#include <gdk/quartz/gdkquartzkeys.h>
#include <gdk/quartz/gdkquartzmonitor.h>
#include <gdk/quartz/gdkquartzscreen.h>
#include <gdk/quartz/gdkquartzutils.h>
#include <gdk/quartz/gdkquartzsurface.h>
#undef __GDKQUARTZ_H_INSIDE__
#endif /* __GDK_QUARTZ_H__ */

View File

@ -1,50 +0,0 @@
/* gdkquartzcursor.h
*
* Copyright (C) 2005-2007 Imendio AB
* Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_CURSOR_H__
#define __GDK_QUARTZ_CURSOR_H__
#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
#define GDK_TYPE_QUARTZ_CURSOR (gdk_quartz_cursor_get_type ())
#define GDK_QUARTZ_CURSOR(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_CURSOR, GdkQuartzCursor))
#define GDK_QUARTZ_CURSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_CURSOR, GdkQuartzCursorClass))
#define GDK_IS_QUARTZ_CURSOR(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_CURSOR))
#define GDK_IS_QUARTZ_CURSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_CURSOR))
#define GDK_QUARTZ_CURSOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_CURSOR, GdkQuartzCursorClass))
#ifdef GTK_COMPILATION
typedef struct _GdkQuartzCursor GdkQuartzCursor;
#else
typedef GdkCursor GdkQuartzCursor;
#endif
typedef struct _GdkQuartzCursorClass GdkQuartzCursorClass;
GDK_AVAILABLE_IN_ALL
GType gdk_quartz_cursor_get_type (void);
G_END_DECLS
#endif /* __GDK_QUARTZ_CURSOR_H__ */

View File

@ -1,44 +0,0 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_DEVICE_CORE_H__
#define __GDK_QUARTZ_DEVICE_CORE_H__
#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
#define GDK_TYPE_QUARTZ_DEVICE_CORE (gdk_quartz_device_core_get_type ())
#define GDK_QUARTZ_DEVICE_CORE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_QUARTZ_DEVICE_CORE, GdkQuartzDeviceCore))
#define GDK_QUARTZ_DEVICE_CORE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_QUARTZ_DEVICE_CORE, GdkQuartzDeviceCoreClass))
#define GDK_IS_QUARTZ_DEVICE_CORE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_QUARTZ_DEVICE_CORE))
#define GDK_IS_QUARTZ_DEVICE_CORE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_QUARTZ_DEVICE_CORE))
#define GDK_QUARTZ_DEVICE_CORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_QUARTZ_DEVICE_CORE, GdkQuartzDeviceCoreClass))
typedef struct _GdkQuartzDeviceCore GdkQuartzDeviceCore;
typedef struct _GdkQuartzDeviceCoreClass GdkQuartzDeviceCoreClass;
GDK_AVAILABLE_IN_ALL
GType gdk_quartz_device_core_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GDK_QUARTZ_DEVICE_CORE_H__ */

View File

@ -1,46 +0,0 @@
/* GDK - The GIMP Drawing Kit
* Copyright (C) 2009 Carlos Garnacho <carlosg@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_DEVICE_MANAGER_CORE_H__
#define __GDK_QUARTZ_DEVICE_MANAGER_CORE_H__
#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
#define GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE (gdk_quartz_device_manager_core_get_type ())
#define GDK_QUARTZ_DEVICE_MANAGER_CORE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE, GdkQuartzDeviceManagerCore))
#define GDK_QUARTZ_DEVICE_MANAGER_CORE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE, GdkQuartzDeviceManagerCoreClass))
#define GDK_IS_QUARTZ_DEVICE_MANAGER_CORE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE))
#define GDK_IS_QUARTZ_DEVICE_MANAGER_CORE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE))
#define GDK_QUARTZ_DEVICE_MANAGER_CORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDK_TYPE_QUARTZ_DEVICE_MANAGER_CORE, GdkQuartzDeviceManagerCoreClass))
typedef struct _GdkQuartzDeviceManagerCore GdkQuartzDeviceManagerCore;
typedef struct _GdkQuartzDeviceManagerCoreClass GdkQuartzDeviceManagerCoreClass;
GDK_AVAILABLE_IN_ALL
GType gdk_quartz_device_manager_core_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GDK_QUARTZ_DEVICE_MANAGER_CORE_H__ */

View File

@ -1,51 +0,0 @@
/* gdkquartzdisplay.h
*
* Copyright (C) 2005-2007 Imendio AB
* Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_DISPLAY_H__
#define __GDK_QUARTZ_DISPLAY_H__
#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
#define GDK_TYPE_QUARTZ_DISPLAY (gdk_quartz_display_get_type ())
#define GDK_QUARTZ_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_DISPLAY, GdkQuartzDisplay))
#define GDK_QUARTZ_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_DISPLAY, GdkQuartzDisplayClass))
#define GDK_IS_QUARTZ_DISPLAY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_DISPLAY))
#define GDK_IS_QUARTZ_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_DISPLAY))
#define GDK_QUARTZ_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_DISPLAY, GdkQuartzDisplayClass))
#ifdef GTK_COMPILATION
typedef struct _GdkQuartzDisplay GdkQuartzDisplay;
#else
typedef GdkDisplay GdkQuartzDisplay;
#endif
typedef struct _GdkQuartzDisplayClass GdkQuartzDisplayClass;
GDK_AVAILABLE_IN_ALL
GType gdk_quartz_display_get_type (void);
G_END_DECLS
#endif /* __GDK_QUARTZ_DISPLAY_H__ */

View File

@ -1,47 +0,0 @@
/* gdkquartzdisplaymanager.h
*
* Copyright (C) 2005-2007 Imendio AB
* Copyright 2010 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_DISPLAY_MANAGER_H__
#define __GDK_QUARTZ_DISPLAY_MANAGER_H__
#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
#define GDK_TYPE_QUARTZ_DISPLAY_MANAGER (gdk_quartz_display_manager_get_type ())
#define GDK_QUARTZ_DISPLAY_MANAGER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_DISPLAY_MANAGER, GdkQuartzDisplayManager))
#ifdef GTK_COMPILATION
typedef struct _GdkQuartzDisplayManager GdkQuartzDisplayManager;
#else
typedef GdkDisplayManager _GdkQuartzDisplayManager;
#endif
typedef struct _GdkDisplayManagerClass GdkQuartzDisplayManagerClass;
GDK_AVAILABLE_IN_ALL
GType gdk_quartz_display_manager_get_type (void);
G_END_DECLS
#endif /* __GDK_QUARTZ_DISPLAY_MANAGER_H__ */

View File

@ -1,56 +0,0 @@
/* gdkquartzdnd.h
*
* Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_DND_H__
#define __GDK_QUARTZ_DND_H__
#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
#define GDK_TYPE_QUARTZ_DRAG_CONTEXT (gdk_quartz_drag_context_get_type ())
#define GDK_QUARTZ_DRAG_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_DRAG_CONTEXT, GdkQuartzDragContext))
#define GDK_QUARTZ_DRAG_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_DRAG_CONTEXT, GdkQuartzDragContextClass))
#define GDK_IS_QUARTZ_DRAG_CONTEXT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_DRAG_CONTEXT))
#define GDK_IS_QUARTZ_DRAG_CONTEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_DRAG_CONTEXT))
#define GDK_QUARTZ_DRAG_CONTEXT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_DRAG_CONTEXT, GdkQuartzDragContextClass))
#ifdef GTK_COMPILATION
typedef struct _GdkQuartzDragContext GdkQuartzDragContext;
#else
typedef GdkDragContext GdkQuartzDragContext;
#endif
typedef struct _GdkQuartzDragContextClass GdkQuartzDragContextClass;
GDK_AVAILABLE_IN_ALL
GType gdk_quartz_drag_context_get_type (void);
GDK_AVAILABLE_IN_ALL
id gdk_quartz_drag_context_get_dragging_info_libgtk_only (GdkDragContext *context);
GDK_AVAILABLE_IN_ALL
GdkDragContext *gdk_quartz_drag_source_context_libgtk_only (void);
G_END_DECLS
#endif /* __GDK_QUARTZ_DRAG_CONTEXT_H__ */

View File

@ -1,50 +0,0 @@
/* gdkquartzkeyd.h
*
* Copyright (C) 2005 Imendio AB
* Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_KEYS_H__
#define __GDK_QUARTZ_KEYS_H__
#if !defined (__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
#define GDK_TYPE_QUARTZ_KEYMAP (gdk_quartz_keymap_get_type ())
#define GDK_QUARTZ_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_KEYMAP, GdkQuartzKeymap))
#define GDK_QUARTZ_KEYMAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_KEYMAP, GdkQuartzKeymapClass))
#define GDK_IS_QUARTZ_KEYMAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_KEYMAP))
#define GDK_IS_QUARTZ_KEYMAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_KEYMAP))
#define GDK_QUARTZ_KEYMAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_KEYMAP, GdkQuartzKeymapClass))
#ifdef GTK_COMPILATION
typedef struct _GdkQuartzKeymap GdkQuartzKeymap;
#else
typedef GdkKeymap GdkQuartzKeymap;
#endif
typedef struct _GdkQuartzKeymapClass GdkQuartzKeymapClass;
GDK_AVAILABLE_IN_ALL
GType gdk_quartz_keymap_get_type (void);
G_END_DECLS
#endif /* __GDK_QUARTZ_KEYS_H__ */

View File

@ -1,45 +0,0 @@
/*
* gdkquartzmonitor.h
*
* Copyright 2017 Tom Schoonjans
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_MONITOR_H__
#define __GDK_QUARTZ_MONITOR_H__
#if !defined (__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
#endif
#include <gdk/gdkmonitor.h>
G_BEGIN_DECLS
#define GDK_TYPE_QUARTZ_MONITOR (gdk_quartz_monitor_get_type ())
#define GDK_QUARTZ_MONITOR(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_MONITOR, GdkQuartzMonitor))
#define GDK_IS_QUARTZ_MONITOR(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_MONITOR))
typedef struct _GdkQuartzMonitor GdkQuartzMonitor;
typedef struct _GdkQuartzMonitorClass GdkQuartzMonitorClass;
GDK_AVAILABLE_IN_ALL
GType gdk_quartz_monitor_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __GDK_QUARTZ_MONITOR_H__ */

View File

@ -1,46 +0,0 @@
/* gdkquartzscreen.h
*
* Copyright (C) 2009, 2010 Kristian Rietveld <kris@gtk.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_SCREEN_H__
#define __GDK_QUARTZ_SCREEN_H__
#if !defined(__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
#endif
G_BEGIN_DECLS
#include <gdk/gdk.h>
#define GDK_TYPE_QUARTZ_SCREEN (gdk_quartz_screen_get_type ())
#define GDK_QUARTZ_SCREEN(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_SCREEN, GdkQuartzScreen))
#define GDK_QUARTZ_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_SCREEN, GdkQuartzScreenClass))
#define GDK_IS_QUARTZ_SCREEN(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_SCREEN))
#define GDK_IS_QUARTZ_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_SCREEN))
#define GDK_QUARTZ_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_SCREEN, GdkQuartzScreenClass))
typedef struct _GdkQuartzScreen GdkQuartzScreen;
typedef struct _GdkQuartzScreenClass GdkQuartzScreenClass;
GDK_AVAILABLE_IN_ALL
GType gdk_quartz_screen_get_type (void);
G_END_DECLS
#endif /* _GDK_QUARTZ_SCREEN_H_ */

View File

@ -1,55 +0,0 @@
/* gdkquartzsurface.h
*
* Copyright (C) 2005 Imendio AB
* Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_SURFACE_H__
#define __GDK_QUARTZ_SURFACE_H__
#if !defined (__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
#define GDK_TYPE_QUARTZ_SURFACE (gdk_quartz_surface_get_type ())
#define GDK_QUARTZ_SURFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_QUARTZ_SURFACE, GdkQuartzSurface))
#define GDK_QUARTZ_SURFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_QUARTZ_SURFACE, GdkQuartzSurfaceClass))
#define GDK_IS_QUARTZ_SURFACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_QUARTZ_SURFACE))
#define GDK_IS_QUARTZ_SURFACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_QUARTZ_SURFACE))
#define GDK_QUARTZ_SURFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_QUARTZ_SURFACE, GdkQuartzSurfaceClass))
#ifdef GTK_COMPILATION
typedef struct _GdkQuartzSurface GdkQuartzSurface;
#else
typedef GdkSurface GdkQuartzSurface;
#endif
typedef struct _GdkQuartzSurfaceClass GdkQuartzSurfaceClass;
GDK_AVAILABLE_IN_ALL
GType gdk_quartz_surface_get_type (void);
GDK_AVAILABLE_IN_ALL
NSWindow *gdk_quartz_surface_get_nswindow (GdkSurface *window);
GDK_AVAILABLE_IN_ALL
NSView *gdk_quartz_surface_get_nsview (GdkSurface *window);
G_END_DECLS
#endif /* __GDK_QUARTZ_SURFACE_H__ */

View File

@ -1,40 +0,0 @@
/* gdkquartzutils.h
*
* Copyright (C) 2005 Imendio AB
* Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_QUARTZ_UTILS_H__
#define __GDK_QUARTZ_UTILS_H__
#if !defined (__GDKQUARTZ_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gdk/quartz/gdkquartz.h> can be included directly."
#endif
#include <gdk/gdk.h>
G_BEGIN_DECLS
GDK_AVAILABLE_IN_ALL
NSImage *gdk_quartz_pixbuf_to_ns_image_libgtk_only (GdkPixbuf *pixbuf);
GDK_AVAILABLE_IN_ALL
NSEvent *gdk_quartz_event_get_nsevent (GdkEvent *event);
GDK_AVAILABLE_IN_ALL
gunichar gdk_quartz_get_key_equivalent (guint key);
G_END_DECLS
#endif /* __GDK_QUARTZ_UTILS_H__ */

View File

@ -1,288 +0,0 @@
/* gdkscreen-quartz.c
*
* Copyright (C) 2005 Imendio AB
* Copyright (C) 2009,2010 Kristian Rietveld <kris@gtk.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gdk/gdk.h>
#include "gdkprivate-quartz.h"
#include "gdkdisplay-quartz.h"
#include "gdkmonitor-quartz.h"
/* A couple of notes about this file are in order. In GDK, a
* GdkScreen can contain multiple monitors. A GdkScreen has an
* associated root window, in which the monitors are placed. The
* root window "spans" all monitors. The origin is at the top-left
* corner of the root window.
*
* Cocoa works differently. The system has a "screen" (NSScreen) for
* each monitor that is connected (note the conflicting definitions
* of screen). The screen containing the menu bar is screen 0 and the
* bottom-left corner of this screen is the origin of the "monitor
* coordinate space". All other screens are positioned according to this
* origin. If the menu bar is on a secondary screen (for example on
* a monitor hooked up to a laptop), then this screen is screen 0 and
* other monitors will be positioned according to the "secondary screen".
* The main screen is the monitor that shows the window that is currently
* active (has focus), the position of the menu bar does not have influence
* on this!
*
* Upon start up and changes in the layout of screens, we calculate the
* size of the GdkScreen root window that is needed to be able to place
* all monitors in the root window. Once that size is known, we iterate
* over the monitors and translate their Cocoa position to a position
* in the root window of the GdkScreen. This happens below in the
* function gdk_quartz_screen_calculate_layout().
*
* A Cocoa coordinate is always relative to the origin of the monitor
* coordinate space. Such coordinates are mapped to their respective
* position in the GdkScreen root window (_gdk_quartz_surface_xy_to_gdk_xy)
* and vice versa (_gdk_quartz_surface_gdk_xy_to_xy). Both functions can
* be found in gdksurface-quartz.c. Note that Cocoa coordinates can have
* negative values (in case a monitor is located left or below of screen 0),
* but GDK coordinates can *not*!
*/
static void gdk_quartz_screen_dispose (GObject *object);
static void gdk_quartz_screen_finalize (GObject *object);
static void gdk_quartz_screen_calculate_layout (GdkQuartzScreen *screen);
static void display_reconfiguration_callback (CGDirectDisplayID display,
CGDisplayChangeSummaryFlags flags,
void *userInfo);
static gint get_mm_from_pixels (NSScreen *screen, int pixels);
G_DEFINE_TYPE (GdkQuartzScreen, gdk_quartz_screen, G_TYPE_OBJECT);
static void
gdk_quartz_screen_init (GdkQuartzScreen *screen)
{
NSDictionary *dd = [[[NSScreen screens] objectAtIndex:0] deviceDescription];
NSSize size = [[dd valueForKey:NSDeviceResolution] sizeValue];
gdk_quartz_screen_calculate_layout (screen);
CGDisplayRegisterReconfigurationCallback (display_reconfiguration_callback, screen);
quartz_screen->emit_monitors_changed = FALSE;
}
static void
gdk_quartz_screen_dispose (GObject *object)
{
GdkQuartzScreen *screen = GDK_QUARTZ_SCREEN (object);
if (screen->screen_changed_id)
{
g_source_remove (screen->screen_changed_id);
screen->screen_changed_id = 0;
}
CGDisplayRemoveReconfigurationCallback (display_reconfiguration_callback, screen);
G_OBJECT_CLASS (gdk_quartz_screen_parent_class)->dispose (object);
}
static void
gdk_quartz_screen_finalize (GObject *object)
{
G_OBJECT_CLASS (gdk_quartz_screen_parent_class)->finalize (object);
}
/* Protocol to build cleanly for OSX < 10.7 */
@protocol ScaleFactor
- (CGFloat) backingScaleFactor;
@end
static void
gdk_quartz_screen_calculate_layout (GdkQuartzScreen *screen)
{
NSArray *array;
int i;
int max_x, max_y;
GdkDisplay *display = screen->display;
GdkQuartzDisplay *display_quartz = GDK_QUARTZ_DISPLAY (display);
g_ptr_array_free (display_quartz->monitors, TRUE);
display_quartz->monitors = g_ptr_array_new_with_free_func (g_object_unref);
GDK_QUARTZ_ALLOC_POOL;
array = [NSScreen screens];
screen->width = 0;
screen->height = 0;
screen->min_x = 0;
screen->min_y = 0;
max_x = max_y = 0;
/* We determine the minimum and maximum x and y coordinates
* covered by the monitors. From this we can deduce the width
* and height of the root screen.
*/
for (i = 0; i < [array count]; i++)
{
GdkQuartzMonitor *monitor = g_object_new (GDK_TYPE_QUARTZ_MONITOR,
"display", display,
NULL);
g_ptr_array_add (display_quartz->monitors, monitor);
monitor->monitor_num = i;
NSRect rect = [[array objectAtIndex:i] frame];
screen->min_x = MIN (screen->min_x, rect.origin.x);
max_x = MAX (max_x, rect.origin.x + rect.size.width);
screen->min_y = MIN (screen->min_y, rect.origin.y);
max_y = MAX (max_y, rect.origin.y + rect.size.height);
}
screen->width = max_x - screen->min_x;
screen->height = max_y - screen->min_y;
for (i = 0; i < [array count] ; i++)
{
NSScreen *nsscreen;
NSRect rect;
GdkMonitor *monitor;
monitor = GDK_MONITOR(display_quartz->monitors->pdata[i]);
nsscreen = [array objectAtIndex:i];
rect = [nsscreen frame];
monitor->geometry.x = rect.origin.x - screen->min_x;
monitor->geometry.y
= screen->height - (rect.origin.y + rect.size.height) + screen->min_y;
monitor->geometry.width = rect.size.width;
monitor->geometry.height = rect.size.height;
if (gdk_quartz_osx_version() >= GDK_OSX_LION)
monitor->scale_factor = [(id <ScaleFactor>) nsscreen backingScaleFactor];
else
monitor->scale_factor = 1;
monitor->width_mm = get_mm_from_pixels(nsscreen, monitor->geometry.width);
monitor->height_mm = get_mm_from_pixels(nsscreen, monitor->geometry.height);
monitor->refresh_rate = 0; // unknown
monitor->manufacturer = NULL; // unknown
monitor->model = NULL; // unknown
monitor->subpixel_layout = GDK_SUBPIXEL_LAYOUT_UNKNOWN; // unknown
}
GDK_QUARTZ_RELEASE_POOL;
}
void
_gdk_quartz_screen_update_window_sizes (GdkQuartzScreen *screen)
{
GList *windows, *list;
/* The size of the root window is so that it can contain all
* monitors attached to this machine. The monitors are laid out
* within this root window. We calculate the size of the root window
* and the positions of the different monitors in gdkscreen-quartz.c.
*
* This data is updated when the monitor configuration is changed.
*/
_gdk_root->x = 0;
_gdk_root->y = 0;
_gdk_root->abs_x = 0;
_gdk_root->abs_y = 0;
windows = get_toplevels ();
for (list = windows; list; list = list->next)
_gdk_quartz_surface_update_position (list->data);
}
static void
process_display_reconfiguration (GdkQuartzScreen *screen)
{
gdk_quartz_screen_calculate_layout (screen);
_gdk_quartz_screen_update_window_sizes (GDK_SCREEN (screen));
}
static gboolean
screen_changed_idle (gpointer data)
{
GdkQuartzScreen *screen = data;
process_display_reconfiguration (data);
screen->screen_changed_id = 0;
return FALSE;
}
static void
display_reconfiguration_callback (CGDirectDisplayID display,
CGDisplayChangeSummaryFlags flags,
void *userInfo)
{
GdkQuartzScreen *screen = userInfo;
if (flags & kCGDisplayBeginConfigurationFlag)
{
/* Ignore the begin configuration signal. */
return;
}
else
{
/* We save information about the changes, so we can emit
* ::monitors-changed when appropriate. This signal must be
* emitted when the number, size of position of one of the
* monitors changes.
*/
if (flags & kCGDisplayMovedFlag
|| flags & kCGDisplayAddFlag
|| flags & kCGDisplayRemoveFlag
|| flags & kCGDisplayEnabledFlag
|| flags & kCGDisplayDisabledFlag)
screen->emit_monitors_changed = TRUE;
/* At this point Cocoa does not know about the new screen data
* yet, so we delay our refresh into an idle handler.
*/
if (!screen->screen_changed_id)
{
screen->screen_changed_id = g_idle_add (screen_changed_idle, screen);
g_source_set_name_by_id (screen->screen_changed_id, "[gtk] screen_changed_idle");
}
}
}
static gint
get_mm_from_pixels (NSScreen *screen, int pixels)
{
const float mm_per_inch = 25.4;
NSDictionary *dd = [[[NSScreen screens] objectAtIndex:0] deviceDescription];
NSSize size = [[dd valueForKey:NSDeviceResolution] sizeValue];
float dpi = size.width;
return (pixels / dpi) * mm_per_inch;
}
static void
gdk_quartz_screen_class_init (GdkQuartzScreenClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gdk_quartz_screen_dispose;
object_class->finalize = gdk_quartz_screen_finalize;
}

View File

@ -1,62 +0,0 @@
/* gdkselection-quartz.c
*
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
* Copyright (C) 1998-2002 Tor Lillqvist
* Copyright (C) 2005 Imendio AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gdkquartz.h"
GdkAtom
gdk_quartz_pasteboard_type_to_atom_libgtk_only (NSString *type)
{
if ([type isEqualToString:NSStringPboardType])
return g_intern_static_string ("UTF8_STRING");
else if ([type isEqualToString:NSTIFFPboardType])
return g_intern_static_string ("image/tiff");
else if ([type isEqualToString:NSColorPboardType])
return g_intern_static_string ("application/x-color");
else if ([type isEqualToString:NSURLPboardType])
return g_intern_static_string ("text/uri-list");
else
return g_intern_string ([type UTF8String]);
}
NSString *
gdk_quartz_target_to_pasteboard_type_libgtk_only (const char *target)
{
if (strcmp (target, "UTF8_STRING") == 0)
return NSStringPboardType;
else if (strcmp (target, "image/tiff") == 0)
return NSTIFFPboardType;
else if (strcmp (target, "application/x-color") == 0)
return NSColorPboardType;
else if (strcmp (target, "text/uri-list") == 0)
return NSURLPboardType;
else
return [NSString stringWithUTF8String:target];
}
NSString *
gdk_quartz_atom_to_pasteboard_type_libgtk_only (GdkAtom atom)
{
const char *target = (const char *)atom;
NSString *ret = gdk_quartz_target_to_pasteboard_type_libgtk_only (target);
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,115 +0,0 @@
/* gdkdrawable-quartz.h
*
* Copyright (C) 2005 Imendio AB
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GDK_SURFACE_QUARTZ_H__
#define __GDK_SURFACE_QUARTZ_H__
#import <gdk/quartz/GdkQuartzView.h>
#import <gdk/quartz/GdkQuartzNSWindow.h>
#include "gdk/gdksurfaceimpl.h"
G_BEGIN_DECLS
/* Window implementation for Quartz
*/
typedef struct _GdkSurfaceImplQuartz GdkSurfaceImplQuartz;
typedef struct _GdkSurfaceImplQuartzClass GdkSurfaceImplQuartzClass;
#define GDK_TYPE_SURFACE_IMPL_QUARTZ (_gdk_surface_impl_quartz_get_type ())
#define GDK_SURFACE_IMPL_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_SURFACE_IMPL_QUARTZ, GdkSurfaceImplQuartz))
#define GDK_SURFACE_IMPL_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_SURFACE_IMPL_QUARTZ, GdkSurfaceImplQuartzClass))
#define GDK_IS_SURFACE_IMPL_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_SURFACE_IMPL_QUARTZ))
#define GDK_IS_SURFACE_IMPL_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_SURFACE_IMPL_QUARTZ))
#define GDK_SURFACE_IMPL_QUARTZ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_SURFACE_IMPL_QUARTZ, GdkSurfaceImplQuartzClass))
struct _GdkSurfaceImplQuartz
{
GdkSurfaceImpl parent_instance;
GdkSurface *wrapper;
NSWindow *toplevel;
NSTrackingRectTag tracking_rect;
GdkQuartzView *view;
GdkSurfaceTypeHint type_hint;
gint in_paint_rect_count;
GdkSurface *transient_for;
/* Sorted by z-order */
GList *sorted_children;
cairo_region_t *needs_display_region;
cairo_surface_t *cairo_surface;
gint shadow_top;
gint shadow_max;
};
struct _GdkSurfaceImplQuartzClass
{
GdkSurfaceImplClass parent_class;
CGContextRef (* get_context) (GdkSurfaceImplQuartz *window,
gboolean antialias);
void (* release_context) (GdkSurfaceImplQuartz *window,
CGContextRef cg_context);
};
GType _gdk_surface_impl_quartz_get_type (void);
CGContextRef gdk_quartz_surface_get_context (GdkSurfaceImplQuartz *window,
gboolean antialias);
void gdk_quartz_surface_release_context (GdkSurfaceImplQuartz *window,
CGContextRef context);
/* Root window implementation for Quartz
*/
typedef struct _GdkRootWindowImplQuartz GdkRootWindowImplQuartz;
typedef struct _GdkRootWindowImplQuartzClass GdkRootWindowImplQuartzClass;
#define GDK_TYPE_ROOT_SURFACE_IMPL_QUARTZ (_gdk_root_surface_impl_quartz_get_type ())
#define GDK_ROOT_SURFACE_IMPL_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_ROOT_SURFACE_IMPL_QUARTZ, GdkRootWindowImplQuartz))
#define GDK_ROOT_SURFACE_IMPL_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_ROOT_SURFACE_IMPL_QUARTZ, GdkRootWindowImplQuartzClass))
#define GDK_IS_ROOT_SURFACE_IMPL_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_ROOT_SURFACE_IMPL_QUARTZ))
#define GDK_IS_ROOT_SURFACE_IMPL_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_ROOT_SURFACE_IMPL_QUARTZ))
#define GDK_ROOT_SURFACE_IMPL_QUARTZ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_ROOT_SURFACE_IMPL_QUARTZ, GdkRootWindowImplQuartzClass))
struct _GdkRootWindowImplQuartz
{
GdkSurfaceImplQuartz parent_instance;
};
struct _GdkRootWindowImplQuartzClass
{
GdkSurfaceImplQuartzClass parent_class;
};
GType _gdk_root_surface_impl_quartz_get_type (void);
GList *get_toplevels (void);
G_END_DECLS
#endif /* __GDK_SURFACE_QUARTZ_H__ */

View File

@ -1,244 +0,0 @@
/* gdkutils-quartz.c
*
* Copyright (C) 2005 Imendio AB
* Copyright (C) 2010 Kristian Rietveld <kris@gtk.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <AppKit/AppKit.h>
#include <gdkquartzutils.h>
#include "gdkprivate-quartz.h"
NSImage *
gdk_quartz_pixbuf_to_ns_image_libgtk_only (GdkPixbuf *pixbuf)
{
NSBitmapImageRep *bitmap_rep;
NSImage *image;
gboolean has_alpha;
has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
/* Create a bitmap image rep */
bitmap_rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL
pixelsWide:gdk_pixbuf_get_width (pixbuf)
pixelsHigh:gdk_pixbuf_get_height (pixbuf)
bitsPerSample:8 samplesPerPixel:has_alpha ? 4 : 3
hasAlpha:has_alpha isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace
bytesPerRow:0 bitsPerPixel:0];
{
/* Add pixel data to bitmap rep */
guchar *src, *dst;
int src_stride, dst_stride;
int x, y;
src_stride = gdk_pixbuf_get_rowstride (pixbuf);
dst_stride = [bitmap_rep bytesPerRow];
for (y = 0; y < gdk_pixbuf_get_height (pixbuf); y++)
{
src = gdk_pixbuf_get_pixels (pixbuf) + y * src_stride;
dst = [bitmap_rep bitmapData] + y * dst_stride;
for (x = 0; x < gdk_pixbuf_get_width (pixbuf); x++)
{
if (has_alpha)
{
guchar red, green, blue, alpha;
red = *src++;
green = *src++;
blue = *src++;
alpha = *src++;
*dst++ = (red * alpha) / 255;
*dst++ = (green * alpha) / 255;
*dst++ = (blue * alpha) / 255;
*dst++ = alpha;
}
else
{
*dst++ = *src++;
*dst++ = *src++;
*dst++ = *src++;
}
}
}
}
image = [[NSImage alloc] init];
[image addRepresentation:bitmap_rep];
[bitmap_rep release];
[image autorelease];
return image;
}
NSEvent *
gdk_quartz_event_get_nsevent (GdkEvent *event)
{
/* FIXME: If the event here is unallocated, we crash. */
return ((GdkEventPrivate *) event)->windowing_data;
}
/*
* Code for key code conversion
*
* Copyright (C) 2009 Paul Davis
*/
gunichar
gdk_quartz_get_key_equivalent (guint key)
{
if (key >= GDK_KEY_A && key <= GDK_KEY_Z)
return key + (GDK_KEY_a - GDK_KEY_A);
if (key >= GDK_KEY_space && key <= GDK_KEY_asciitilde)
return key;
switch (key)
{
case GDK_KEY_BackSpace:
return NSBackspaceCharacter;
case GDK_KEY_Delete:
return NSDeleteFunctionKey;
case GDK_KEY_Pause:
return NSPauseFunctionKey;
case GDK_KEY_Scroll_Lock:
return NSScrollLockFunctionKey;
case GDK_KEY_Sys_Req:
return NSSysReqFunctionKey;
case GDK_KEY_Home:
return NSHomeFunctionKey;
case GDK_KEY_Left:
case GDK_KEY_leftarrow:
return NSLeftArrowFunctionKey;
case GDK_KEY_Up:
case GDK_KEY_uparrow:
return NSUpArrowFunctionKey;
case GDK_KEY_Right:
case GDK_KEY_rightarrow:
return NSRightArrowFunctionKey;
case GDK_KEY_Down:
case GDK_KEY_downarrow:
return NSDownArrowFunctionKey;
case GDK_KEY_Page_Up:
return NSPageUpFunctionKey;
case GDK_KEY_Page_Down:
return NSPageDownFunctionKey;
case GDK_KEY_End:
return NSEndFunctionKey;
case GDK_KEY_Begin:
return NSBeginFunctionKey;
case GDK_KEY_Select:
return NSSelectFunctionKey;
case GDK_KEY_Print:
return NSPrintFunctionKey;
case GDK_KEY_Execute:
return NSExecuteFunctionKey;
case GDK_KEY_Insert:
return NSInsertFunctionKey;
case GDK_KEY_Undo:
return NSUndoFunctionKey;
case GDK_KEY_Redo:
return NSRedoFunctionKey;
case GDK_KEY_Menu:
return NSMenuFunctionKey;
case GDK_KEY_Find:
return NSFindFunctionKey;
case GDK_KEY_Help:
return NSHelpFunctionKey;
case GDK_KEY_Break:
return NSBreakFunctionKey;
case GDK_KEY_Mode_switch:
return NSModeSwitchFunctionKey;
case GDK_KEY_F1:
return NSF1FunctionKey;
case GDK_KEY_F2:
return NSF2FunctionKey;
case GDK_KEY_F3:
return NSF3FunctionKey;
case GDK_KEY_F4:
return NSF4FunctionKey;
case GDK_KEY_F5:
return NSF5FunctionKey;
case GDK_KEY_F6:
return NSF6FunctionKey;
case GDK_KEY_F7:
return NSF7FunctionKey;
case GDK_KEY_F8:
return NSF8FunctionKey;
case GDK_KEY_F9:
return NSF9FunctionKey;
case GDK_KEY_F10:
return NSF10FunctionKey;
case GDK_KEY_F11:
return NSF11FunctionKey;
case GDK_KEY_F12:
return NSF12FunctionKey;
case GDK_KEY_F13:
return NSF13FunctionKey;
case GDK_KEY_F14:
return NSF14FunctionKey;
case GDK_KEY_F15:
return NSF15FunctionKey;
case GDK_KEY_F16:
return NSF16FunctionKey;
case GDK_KEY_F17:
return NSF17FunctionKey;
case GDK_KEY_F18:
return NSF18FunctionKey;
case GDK_KEY_F19:
return NSF19FunctionKey;
case GDK_KEY_F20:
return NSF20FunctionKey;
case GDK_KEY_F21:
return NSF21FunctionKey;
case GDK_KEY_F22:
return NSF22FunctionKey;
case GDK_KEY_F23:
return NSF23FunctionKey;
case GDK_KEY_F24:
return NSF24FunctionKey;
case GDK_KEY_F25:
return NSF25FunctionKey;
case GDK_KEY_F26:
return NSF26FunctionKey;
case GDK_KEY_F27:
return NSF27FunctionKey;
case GDK_KEY_F28:
return NSF28FunctionKey;
case GDK_KEY_F29:
return NSF29FunctionKey;
case GDK_KEY_F30:
return NSF30FunctionKey;
case GDK_KEY_F31:
return NSF31FunctionKey;
case GDK_KEY_F32:
return NSF32FunctionKey;
case GDK_KEY_F33:
return NSF33FunctionKey;
case GDK_KEY_F34:
return NSF34FunctionKey;
case GDK_KEY_F35:
return NSF35FunctionKey;
default:
break;
}
return '\0';
}

View File

@ -1,45 +0,0 @@
# FIXME: do we need to do an add_language() for objective-c here?
gdk_quartz_sources = files([
'GdkQuartzView.c',
'GdkQuartzNSWindow.c',
'gdkcairocontext-quartz.c',
'gdkcursor-quartz.c',
'gdkdevice-core-quartz.c',
'gdkdevicemanager-core-quartz.c',
'gdkdisplay-quartz.c',
'gdkdisplaymanager-quartz.c',
'gdkdnd-quartz.c',
'gdkevents-quartz.c',
'gdkeventloop-quartz.c',
'gdkglcontext-quartz.c',
'gdkglobals-quartz.c',
'gdkkeys-quartz.c',
'gdkscreen-quartz.c',
'gdkselection-quartz.c',
'gdkutils-quartz.c',
'gdksurface-quartz.c',
])
gdk_quartz_public_headers = files([
'gdkquartzcursor.h',
'gdkquartzdevice-core.h',
'gdkquartzdevicemanager-core.h',
'gdkquartzdisplay.h',
'gdkquartzdisplaymanager.h',
'gdkquartzdnd.h',
'gdkquartzkeys.h',
'gdkquartzscreen.h',
'gdkquartzutils.h',
'gdkquartzsurface.h',
])
install_headers(gdk_quartz_public_headers, 'gdkquartz.h', subdir: 'gtk-4.0/gdk/quartz/')
gdk_quartz_deps = [ # FIXME
]
libgdk_quartz = static_library('gdk-quartz',
gdk_quartz_sources, gdkconfig, gdkenum_h,
include_directories: [confinc, gdkinc],
c_args: ['-DGTK_COMPILATION', '-DG_LOG_DOMAIN="Gdk"', '-xobjective-c'],
dependencies: [gdk_deps, gdk_quartz_deps])

View File

@ -1,156 +0,0 @@
static const struct { gint width, height; gint hotx, hoty; const guchar *bits; } xcursors[] = {
{ 14, 14, 6, 6, (guchar *) "\x07\xb8\x0f\x3c\x1f\x3e\x3e\x1f\xfc\x0f\xf8\x07\xf0\x03\xf0\x03\xf8\x07\xfc\x0f\x3e\x1f\x1f\x3e\x0f\x3c\x07\x38" },
{ 16, 16, 7, 7, (guchar *) "\x0f\xf0\x1f\xf8\x3f\xfc\x7f\xfe\xfe\x7f\xfc\x3f\xf8\x1f\xf0\x0f\xf0\x0f\xf8\x1f\xfc\x3f\xfe\x7f\x7f\xfe\x3f\xfc\x1f\xf8\x0f\xf0" },
{ 14, 14, 13, 0, (guchar *) "\x00\xb0\x00\x3c\x00\x1f\xc0\x1f\xf0\x0f\xfc\x0f\xc0\x07\xe0\x07\x70\x03\x38\x03\x1c\x01\x0e\x01\x07\x00\x02\x00" },
{ 16, 16, 14, 1, (guchar *) "\x00\xe0\x00\xf8\x00\xfe\x80\x7f\xe0\x7f\xf8\x3f\xfc\x3f\xfc\x1f\xe0\x1f\xf0\x0f\xf8\x0f\x7c\x07\x3e\x07\x1f\x02\x0e\x00\x04\x00" },
{ 8, 10, 3, 9, (guchar *) "\xff\x00\xff\x18\x18\x18\x18\x5a\x3c\x18" },
{ 10, 12, 4, 10, (guchar *) "\xff\x23\xff\x03\xff\x03\xff\x03\xff\x03\x78\x00\x78\x00\xfe\x01\xfe\x01\xfe\x01\xfc\x00\x78\x00" },
{ 8, 10, 3, 9, (guchar *) "\x18\x3c\x5a\x18\x18\x18\x18\xff\x00\xff" },
{ 10, 12, 4, 10, (guchar *) "\x30\x20\x78\x00\xfe\x01\xfe\x01\xfe\x01\x78\x00\x78\x00\xff\x03\xff\x03\xff\x03\xff\x03\xff\x03" },
{ 16, 8, 14, 3, (guchar *) "\x80\x00\xe0\x03\x11\x06\xff\xff\x00\x18\x00\x04\x00\x02\xff\x03" },
{ 16, 9, 14, 4, (guchar *) "\xe0\x00\xf0\x03\xf9\x07\xff\xff\xff\xff\xff\xff\xff\x1f\xff\x07\xff\x03" },
{ 13, 14, 6, 6, (guchar *) "\x47\x9c\x44\x04\x44\x04\x44\x04\xff\x1f\x45\x14\x45\x14\x45\x14\x45\x14\xff\x1f\x44\x04\x44\x04\x44\x04\x47\x1c" },
{ 15, 16, 7, 7, (guchar *) "\xdf\x7d\xdf\x7d\xdf\x7d\xdc\x1d\xff\x7f\xff\x7f\xff\x7f\xdf\x7d\xdf\x7d\xff\x7f\xff\x7f\xff\x7f\xdc\x1d\xdf\x7d\xdf\x7d\xdf\x7d" },
{ 14, 14, 0, 13, (guchar *) "\x03\x80\x03\x00\x23\x08\x23\x04\x23\x02\x23\x01\xa3\x00\x63\x00\xe3\x0f\x03\x00\x03\x00\x03\x00\xff\x3f\xff\x3f" },
{ 16, 16, 1, 14, (guchar *) "\x0f\x00\x0f\x00\xef\x30\xef\x38\xef\x1c\xef\x0e\xef\x07\xef\x03\xef\x3f\xef\x3f\xef\x3f\x0f\x00\xff\xff\xff\xff\xff\xff\xff\xff" },
{ 14, 14, 13, 13, (guchar *) "\x00\xb0\x00\x30\x04\x31\x08\x31\x10\x31\x20\x31\x40\x31\x80\x31\xfc\x31\x00\x30\x00\x30\x00\x30\xff\x3f\xff\x3f" },
{ 16, 16, 14, 14, (guchar *) "\x00\xf0\x00\xf0\x0c\xf7\x1c\xf7\x38\xf7\x70\xf7\xe0\xf7\xc0\xf7\xfc\xf7\xfc\xf7\xfc\xf7\x00\xf0\xff\xff\xff\xff\xff\xff\xff\xff" },
{ 13, 14, 6, 13, (guchar *) "\x40\x80\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x44\x04\x48\x02\x50\x01\xe0\x00\x40\x00\x00\x00\xff\x1f\xff\x1f" },
{ 15, 16, 7, 14, (guchar *) "\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xcc\x19\xdc\x1d\xf8\x0f\xf0\x07\xe0\x03\xc0\x01\xff\x7f\xff\x7f\xff\x7f\xff\x7f" },
{ 14, 10, 7, 9, (guchar *) "\xc0\x80\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xff\x3f\xff\x3f" },
{ 16, 12, 8, 10, (guchar *) "\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xff\xff\xff\xff\xff\xff\xff\xff" },
{ 15, 16, 8, 8, (guchar *) "\xff\xff\x01\x00\xfd\x7f\x05\x40\xf5\x5f\x15\x50\xd5\x57\x55\x54\x55\x55\xd5\x55\x15\x54\xf5\x57\x05\x50\xfd\x5f\x01\x40\xff\x7f" },
{ 16, 16, 8, 8, (guchar *) "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" },
{ 10, 14, 4, 0, (guchar *) "\x30\x90\x30\x00\x78\x00\x78\x00\xfc\x00\xfc\x00\xfe\x01\xfe\x01\x33\x03\x31\x02\x30\x00\x30\x00\x30\x00\x30\x00" },
{ 12, 16, 5, 1, (guchar *) "\xf0\x20\xf0\x00\xf8\x01\xf8\x01\xfc\x03\xfc\x03\xfe\x07\xfe\x07\xff\x0f\xff\x0f\xff\x0f\xf7\x0e\xf0\x00\xf0\x00\xf0\x00\xf0\x00" },
{ 14, 14, 7, 7, (guchar *) "\xe0\x81\xf8\x07\xfc\x0f\x1e\x1e\x0e\x1c\x07\x38\x07\x38\x07\x38\x07\x38\x0e\x1c\x1e\x1e\xfc\x0f\xf8\x07\xe0\x01" },
{ 16, 16, 8, 8, (guchar *) "\xe0\x07\xf8\x1f\xfc\x3f\xfe\x7f\xfe\x7f\x3f\xfc\x1f\xf8\x1f\xf8\x1f\xf8\x1f\xf8\x3f\xfc\xfe\x7f\xfe\x7f\xfc\x3f\xf8\x1f\xe0\x07" },
{ 14, 16, 6, 3, (guchar *) "\xfc\x8f\xe6\x19\x13\x33\xc9\x24\x79\x24\x11\x22\xe3\x31\xfe\x1f\xca\x14\xca\x14\xca\x14\xea\x15\xcb\x34\x0f\x3c\xff\x3f\xff\x3f" },
{ 15, 16, 6, 3, (guchar *) "\xfe\x1f\xf7\x39\xdb\x77\xed\x6d\xfd\x6f\xf9\x66\xf3\x73\xff\x3f\xeb\x35\xeb\x35\xeb\x35\xfb\x37\xeb\x75\xcf\x7c\xff\x7f\xff\x7f" },
{ 15, 16, 7, 9, (guchar *) "\xf8\x8f\x04\x10\x06\x60\x0a\x58\xf2\x47\x03\x40\x03\x40\x02\x40\x02\x40\x9a\x58\x56\x55\xd7\x55\x5b\x59\x02\x40\x02\x40\xfc\x3f" },
{ 16, 16, 7, 9, (guchar *) "\xf8\x0f\xfc\x1f\xfe\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xfc\x3f" },
{ 16, 15, 7, 7, (guchar *) "\x40\x01\x40\x01\x40\x01\x40\x01\x40\x01\x40\x01\x7f\xff\x00\x00\x7f\xff\x40\x01\x40\x01\x40\x01\x40\x01\x40\x01\x40\x01" },
{ 16, 16, 7, 7, (guchar *) "\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x03\xe0\x03" },
{ 16, 15, 7, 7, (guchar *) "\x42\x21\x45\x51\x4a\x29\x54\x15\x68\x0b\x50\x05\xbf\xfe\x40\x01\xbf\xfe\x50\x05\x68\x0b\x54\x15\x4a\x29\x45\x51\x42\x21" },
{ 16, 15, 7, 7, (guchar *) "\x66\x33\x6d\xdb\x7b\x6f\x76\x37\x6c\x1b\x5f\xfd\x3f\xfe\x80\x00\x3f\xfe\x5f\xfd\x6c\x1b\x76\x37\x7b\x6f\x6d\xdb\x66\x33" },
{ 16, 15, 7, 7, (guchar *) "\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00\x7f\xff\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00" },
{ 16, 16, 7, 7, (guchar *) "\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xff\xff\xff\xff\xff\xff\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01" },
{ 15, 15, 7, 7, (guchar *) "\x40\x81\x60\x03\x50\x05\x48\x09\x44\x11\x42\x21\x7f\x7f\x00\x00\x7f\x7f\x42\x21\x44\x11\x48\x09\x50\x05\x60\x03\x40\x01" },
{ 16, 16, 7, 7, (guchar *) "\xe0\x03\xf0\x07\xf8\x0f\xdc\x1d\xce\x39\xc7\x71\xff\xff\x7f\xff\xff\xff\xc7\x71\xce\x39\xdc\x1d\xf8\x0f\xf0\x07\xe0\x03\xc0\x01" },
{ 10, 10, 5, 5, (guchar *) "\x78\x90\xfe\x01\xfe\x01\xff\x03\xff\x03\xff\x03\xff\x03\xfe\x01\xfe\x01\x78\x00" },
{ 12, 12, 6, 6, (guchar *) "\xf8\x21\xfe\x07\xfe\x07\xff\x0f\xff\x0f\xff\x0f\xff\x0f\xff\x0f\xff\x0f\xfe\x07\xfe\x07\xf8\x01" },
{ 12, 12, 6, 5, (guchar *) "\xff\x9f\x01\x08\x01\x08\x01\x08\x01\x08\x61\x08\x61\x08\x01\x08\x01\x08\x01\x08\x01\x08\xff\x0f" },
{ 14, 14, 7, 6, (guchar *) "\xff\x3f\xff\x3f\xff\x3f\x07\x38\x07\x38\xe7\x39\xe7\x39\xe7\x39\xe7\x39\x07\x38\x07\x38\xff\x3f\xff\x3f\xff\x3f" },
{ 10, 14, 5, 7, (guchar *) "\x30\x90\x78\x00\xfc\x00\xb6\x01\x33\x03\x30\x00\x30\x00\x30\x00\x30\x00\x33\x03\xb6\x01\xfc\x00\x78\x00\x30\x00" },
{ 12, 16, 6, 8, (guchar *) "\xf0\x20\xf8\x01\xfc\x03\xfe\x07\xff\x0f\xff\x0f\xff\x0f\xf0\x00\xf0\x00\xff\x0f\xff\x0f\xff\x0f\xfe\x07\xfc\x03\xf8\x01\xf0\x00" },
{ 15, 15, 14, 0, (guchar *) "\x00\xc0\x00\x30\x00\x3c\x00\x1f\xc0\x1f\xf0\x0f\xfc\x0f\x80\x07\x40\x07\x20\x03\x10\x03\x08\x01\x04\x01\x02\x00\x01\x00" },
{ 15, 16, 14, 0, (guchar *) "\x00\x60\x00\x78\x00\x7e\x80\x3f\xe0\x1f\xf8\x1f\xfe\x0f\xfe\x0f\xe0\x07\xf0\x07\xb8\x03\x9c\x03\x8e\x01\x87\x01\x03\x00\x01\x00" },
{ 15, 15, 14, 0, (guchar *) "\x00\x40\x00\x30\x00\x3c\x00\x1f\xc0\x1f\x00\x0e\x00\x0d\x80\x04\x40\x04\x20\x00\x10\x00\x08\x00\x04\x00\x02\x00\x01\x00" },
{ 15, 15, 14, 0, (guchar *) "\x00\x60\x00\x78\x00\x3e\x80\x3f\xe0\x1f\xe0\x1f\x80\x0f\xc0\x0f\xe0\x06\x70\x02\x38\x00\x1c\x00\x0e\x00\x07\x00\x03\x00" },
{ 12, 12, 6, 5, (guchar *) "\xff\x1f\x91\x08\x99\x09\x0d\x0b\x07\x0e\x61\x08\x61\x08\x07\x0e\x0d\x0b\x99\x09\x91\x08\xff\x0f" },
{ 14, 14, 7, 6, (guchar *) "\xff\x3f\xff\x3f\xf3\x33\xfb\x37\x3f\x3f\xdf\x3e\xef\x3d\xef\x3d\xdf\x3e\x3f\x3f\xfb\x37\xf3\x33\xff\x3f\xff\x3f" },
{ 14, 14, 6, 6, (guchar *) "\xf1\x03\xfb\x07\x1f\x0c\x09\x08\x19\x00\x3f\x00\x00\x00\x00\x00\x00\x3f\x00\x26\x04\x24\x0c\x3e\xf8\x37\xf0\x23" },
{ 16, 16, 7, 7, (guchar *) "\xe3\x07\xf7\x0f\xff\x1f\xff\x3f\x3f\x38\xff\x30\xff\x00\xff\x00\x00\xff\x00\xff\x0c\xfe\x1c\xfc\xfc\xff\xf8\xff\xf0\xef\xe0\xc7" },
{ 14, 14, 7, 7, (guchar *) "\xc0\x00\xe0\x01\xf0\x03\xc0\x00\xc4\x08\xc6\x18\xff\x3f\xff\x3f\xc6\x18\xc4\x08\xc0\x00\xf0\x03\xe0\x01\xc0\x00" },
{ 16, 16, 8, 8, (guchar *) "\xc0\x03\xc0\x07\xe0\x07\xf0\x0f\xe8\x17\xdc\x3b\xff\xff\xff\xff\xff\xff\xff\xff\xdc\x3b\xe8\x17\xf0\x0f\xe0\x07\xc0\x03\xc0\x03" },
{ 16, 15, 14, 2, (guchar *) "\x00\x1e\x00\x0e\x01\xcc\xf9\x0d\xff\x0f\x7f\x0c\x3f\x0c\x06\x1c\x00\x0f\xf8\x07\x10\x00\x10\x00\x10\x00\x10\x00\x78\x00" },
{ 16, 16, 14, 3, (guchar *) "\x00\x3f\x00\x3f\x03\xff\xff\xff\xff\xff\xff\x3f\xff\x3f\xff\x3f\xff\x3f\xff\x3f\xfe\x1f\xf8\x0f\x38\x00\x38\x00\xfc\x00\xfc\x00" },
{ 16, 16, 2, 0, (guchar *) "\xfc\x00\x08\x01\x13\x02\x57\x05\x13\x04\xd3\x05\x1f\x3c\x1c\xfc\x10\xe4\x10\xe4\x90\xf4\x90\xe4\x90\x04\x88\x08\x84\x10\x7c\x1f" },
{ 16, 16, 2, 0, (guchar *) "\xfc\x00\xfb\x01\xf7\x03\xff\x07\xf7\x07\xf7\x3f\xff\x7f\xff\xff\xfc\xf7\xf0\xf7\xf0\xff\xf0\xf7\xf0\xe7\xf8\x0f\xfc\x1f\x7c\x1f" },
{ 13, 16, 12, 0, (guchar *) "\x00\x18\x00\x1e\x80\x07\xc0\x03\xe0\x01\xf0\x03\xf8\x07\xfa\x03\xff\x07\xfd\x07\xf0\x03\xf0\x01\x29\x00\x23\x00\x16\x00\x0c\x00" },
{ 13, 16, 12, 0, (guchar *) "\x00\xdc\x00\x1f\xc0\x0f\xe0\x07\xf0\x03\xf8\x07\xfe\x0f\xff\x0f\xff\x0f\xff\x0f\xff\x07\xff\x03\xff\x01\x7f\x00\x3f\x00\x1e\x00" },
{ 15, 14, 0, 0, (guchar *) "\xfe\x01\x01\x02\x7e\x04\x08\x08\x70\x08\x08\x08\x70\x14\x08\x22\x30\x41\xc0\x20\x40\x12\x80\x08\x00\x05\x00\x02" },
{ 16, 16, 0, 1, (guchar *) "\xfe\x01\xff\x03\xff\x07\xff\x0f\xfe\x1f\xf8\x1f\xfc\x1f\xf8\x3f\xfc\x7f\xf8\xff\xf0\x7f\xe0\x3f\xc0\x1f\x80\x0f\x00\x07\x00\x02" },
{ 15, 14, 6, 8, (guchar *) "\x7c\x1f\xc6\x31\x83\x60\x01\x40\x01\x40\x01\x40\x01\x40\x03\x60\x06\x30\x0c\x18\x18\x0c\x30\x06\x60\x03\xc0\x01" },
{ 15, 14, 6, 8, (guchar *) "\x7c\x9f\xfe\x3f\xc7\x71\x83\x60\x03\x60\x03\x60\x43\x61\x87\x70\x0e\x38\x1c\x1c\x38\x0e\xf0\x07\xe0\x03\xc0\x01" },
{ 16, 16, 8, 8, (guchar *) "\xff\xff\xab\xaa\x55\xd5\xab\xaa\x05\xd0\x0b\xa0\x05\xd0\x0b\xa0\x05\xd0\x0b\xa0\x05\xd0\x0b\xa0\x55\xd5\xab\xaa\x55\xd5\xff\xff" },
{ 16, 16, 8, 8, (guchar *) "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" },
{ 14, 14, 7, 6, (guchar *) "\xfe\x1f\xfc\x0f\xf9\x27\xf3\x33\xe7\x39\xcf\x3c\xff\x3f\xff\x3f\xcf\x3c\xe7\x39\xf3\x33\xf9\x27\xfc\x0f\xfe\x1f" },
{ 16, 16, 8, 7, (guchar *) "\xfc\x3f\xfe\x7f\xfe\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x7f\xfe\x7f\xfc\x3f" },
{ 8, 14, 0, 0, (guchar *) "\x01\x03\x07\x0f\x1f\x3f\x7f\xff\x1f\x1b\x31\x30\x60\x60" },
{ 10, 16, 1, 1, (guchar *) "\x03\xc0\x07\x00\x0f\x00\x1f\x00\x3f\x00\x7f\x00\xff\x00\xff\x01\xff\x03\xff\x03\x7f\x00\xf7\x00\xf3\x00\xe0\x01\xe0\x01\xc0\x00" },
{ 14, 13, 0, 6, (guchar *) "\x03\x00\x03\x00\x83\x00\x43\x00\x23\x00\x13\x00\xfb\x3f\x13\x00\x23\x00\x43\x00\x83\x00\x03\x00\x03\x00" },
{ 16, 15, 1, 7, (guchar *) "\x0f\x00\x0f\x00\x0f\x03\x8f\x03\xcf\x01\xef\x00\xff\xff\xff\xff\xff\xff\xef\x00\xcf\x01\x8f\x03\x0f\x03\x0f\x00\x0f\x00" },
{ 10, 14, 0, 7, (guchar *) "\x03\x10\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\xff\x03\xff\x03\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00" },
{ 12, 16, 1, 8, (guchar *) "\x0f\xc0\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\xff\x0f\xff\x0f\xff\x0f\xff\x0f\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00" },
{ 16, 16, 8, 8, (guchar *) "\x01\xc0\xfe\xbf\xfe\xbf\x22\xa2\xa2\xaa\xa2\xaa\xa2\xaa\xa2\xaa\x22\xa2\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\x01\xc0" },
{ 15, 16, 8, 8, (guchar *) "\xfe\xbf\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xfe\x3f" },
{ 10, 10, 0, 9, (guchar *) "\x03\x10\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\xff\x03\xff\x03" },
{ 12, 12, 1, 10, (guchar *) "\x0f\xc0\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\xff\x0f\xff\x0f\xff\x0f\xff\x0f" },
{ 10, 10, 9, 9, (guchar *) "\x00\x13\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\xff\x03\xff\x03" },
{ 12, 12, 10, 10, (guchar *) "\x00\xcf\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\xff\x0f\xff\x0f\xff\x0f\xff\x0f" },
{ 16, 16, 14, 5, (guchar *) "\xc0\x01\x78\x0f\x40\x01\x81\x00\xc2\xe1\x24\xd2\xb8\x0e\xa0\x02\x20\x02\x40\x01\x20\x02\x90\x04\x48\x09\x28\x0a\x1e\x3c\x1f\xfc" },
{ 16, 16, 14, 5, (guchar *) "\xf8\x07\xfc\x0f\xfc\x1f\xc3\x41\xe7\xe3\xfe\xff\xfc\xdf\xf8\x0f\xe0\x07\xe0\x03\xf0\x07\xf8\x0f\xfc\x1f\x7e\x3f\x3f\xfe\x3f\xfe" },
{ 16, 16, 8, 8, (guchar *) "\x01\xc0\xfe\xbf\xfe\xbf\x22\xa2\x2a\xaa\x2a\xaa\x2a\xaa\x2a\xaa\x22\xa2\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\x01\xc0" },
{ 15, 16, 8, 8, (guchar *) "\xfe\xbf\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xfe\x3f" },
{ 15, 14, 4, 1, (guchar *) "\xe0\x00\x30\x00\x60\x00\xc0\x00\xfe\x1f\x01\x20\xcd\x6c\xcd\x6c\xcd\x6c\x01\x60\x01\x60\x06\x38\x18\x06\xe0\x01" },
{ 16, 16, 4, 1, (guchar *) "\xf0\x01\x78\x00\xf0\x00\xe0\x00\xfe\x1f\xff\x3f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\xef\xf8\x07\xf0\x03\xe0\x01" },
{ 11, 16, 10, 15, (guchar *) "\x0e\x10\x11\x00\x31\x00\x52\x00\x5e\x00\x84\x00\x88\x00\x08\x01\x10\x01\x30\x02\x20\x02\x40\x04\x80\x07\x00\x07\x00\x06\x00\x04" },
{ 13, 16, 11, 15, (guchar *) "\x3f\xc0\x7f\x00\xff\x00\xfe\x00\xfc\x01\xfc\x01\xf8\x03\xf0\x03\xf0\x07\xe0\x07\xe0\x0f\xc0\x1f\x80\x1f\x00\x1f\x00\x1e\x00\x1c" },
{ 15, 16, 7, 12, (guchar *) "\xe0\x01\xf0\x03\xf8\x07\xcc\x0c\xcc\x0c\xf8\x07\xf0\x03\xe0\x01\xe1\x21\xe1\x61\xc2\x10\x1c\x0e\xe0\x01\xf8\x47\x0f\x7c\x01\x20" },
{ 16, 16, 7, 12, (guchar *) "\xf0\x03\xf8\x07\xfc\x0f\xfe\x1f\xfe\x1f\xfc\x0f\xf8\x07\xf1\x83\xf1\xe3\xf3\xf3\xef\x39\x1e\x1e\xe0\x01\xfe\xc7\xff\xff\x0f\x7c" },
{ 10, 10, 4, 5, (guchar *) "\x30\x10\x30\x00\x30\x00\x30\x00\xff\x03\xff\x03\x30\x00\x30\x00\x30\x00\x30\x00" },
{ 12, 12, 5, 6, (guchar *) "\xf0\xc0\xf0\x00\xf0\x00\xf0\x00\xff\x0f\xff\x0f\xff\x0f\xff\x0f\xf0\x00\xf0\x00\xf0\x00\xf0\x00" },
{ 9, 15, 4, 7, (guchar *) "\x7c\x10\xfe\x00\xc7\x01\x83\x01\x87\x01\xc6\x01\xe0\x00\x78\x00\x38\x00\x28\x00\x28\x00\xee\x00\x6c\x00\x38\x00\x10\x00" },
{ 11, 16, 5, 8, (guchar *) "\xf8\xc0\xfc\x01\xfe\x03\xff\x07\x8f\x07\x9f\x07\xde\x07\xfc\x03\xf8\x01\xf8\x00\xf8\x00\xfc\x01\xfe\x03\xfc\x01\xf8\x00\x70\x00" },
{ 8, 14, 7, 0, (guchar *) "\x80\xc0\xe0\xf0\xf8\xfc\xfe\xff\xf8\xd8\x8c\x0c\x06\x06" },
{ 10, 16, 8, 1, (guchar *) "\x00\xc3\x80\x03\xc0\x03\xe0\x03\xf0\x03\xf8\x03\xfc\x03\xfe\x03\xff\x03\xff\x03\xf8\x03\xbc\x03\x3c\x03\x1e\x00\x1e\x00\x0c\x00" },
{ 14, 13, 13, 6, (guchar *) "\x00\x30\x00\x30\x40\x30\x80\x30\x00\x31\x00\x32\xff\x37\x00\x32\x00\x31\x80\x30\x40\x30\x00\x30\x00\x30" },
{ 16, 15, 14, 7, (guchar *) "\x00\xf0\x00\xf0\xc0\xf0\xc0\xf1\x80\xf3\x00\xf7\xff\xff\xff\xff\xff\xff\x00\xf7\x80\xf3\xc0\xf1\xc0\xf0\x00\xf0\x00\xf0" },
{ 10, 14, 9, 7, (guchar *) "\x00\x13\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\xff\x03\xff\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03" },
{ 12, 16, 10, 8, (guchar *) "\x00\xcf\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\xff\x0f\xff\x0f\xff\x0f\xff\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f" },
{ 16, 16, 8, 8, (guchar *) "\x01\xc0\xfe\xbf\xfe\xbf\x22\xa2\xaa\xa2\xaa\xa2\xaa\xa2\xaa\xa2\x22\xa2\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\xfe\xbf\x01\xc0" },
{ 15, 16, 8, 8, (guchar *) "\xfe\xbf\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xfe\x3f" },
{ 14, 14, 6, 6, (guchar *) "\xff\x3f\x01\x22\x01\x22\x01\x22\xff\x23\x11\x22\x11\x22\x11\x22\x11\x22\xf1\x3f\x11\x20\x11\x20\x11\x20\xff\x3f" },
{ 16, 16, 7, 7, (guchar *) "\xff\xff\xff\xff\xff\xff\x07\xee\xff\xef\xff\xef\xff\xef\x77\xee\x77\xee\xf7\xff\xf7\xff\xf7\xff\x77\xe0\xff\xff\xff\xff\xff\xff" },
{ 12, 13, 6, -1, (guchar *) "\x80\x10\x80\x00\xa0\x01\xa0\x01\xb0\x01\xb0\x03\xb8\x03\xb8\x03\xbc\x07\xbc\x07\xbe\x07\xbe\x0f\x1f\x07" },
{ 16, 16, 8, 0, (guchar *) "\x00\x03\x00\x07\x80\x07\xc0\x0f\xc0\x0f\xe0\x0f\xe0\x1f\xf0\x1f\xf0\x1f\xf8\x3f\xf8\x3f\xfc\x3f\xfc\xff\xfe\xff\xff\x1f\xfe\x07" },
{ 7, 15, 3, 15, (guchar *) "\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x7f\x3e\x1c\x08" },
{ 9, 16, 4, 15, (guchar *) "\x7c\xc0\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\xff\x01\xff\x01\xfe\x00\x7c\x00\x38\x00\x10\x00" },
{ 15, 7, 7, 3, (guchar *) "\x08\x08\x0c\x18\xfe\x3f\x0f\x78\xfe\x3f\x0c\x18\x08\x08" },
{ 15, 9, 7, 4, (guchar *) "\x18\x8c\x1c\x1c\xfe\x3f\xff\x7f\xff\x7f\xff\x7f\xfe\x3f\x1c\x1c\x18\x0c" },
{ 15, 7, -1, 3, (guchar *) "\x08\x00\x0c\x00\xfe\x7f\x0f\x00\xfe\x7f\x0c\x00\x08\x00" },
{ 16, 9, 0, 4, (guchar *) "\x30\x00\x38\x00\xfc\xff\xfe\xff\xff\xff\xfe\xff\xfc\xff\x38\x00\x30\x00" },
{ 15, 7, 15, 3, (guchar *) "\x00\x08\x00\x18\xff\x3f\x00\x78\xff\x3f\x00\x18\x00\x08" },
{ 16, 9, 15, 4, (guchar *) "\x00\x0c\x00\x1c\xff\x3f\xff\x7f\xff\xff\xff\x7f\xff\x3f\x00\x1c\x00\x0c" },
{ 7, 15, 3, -1, (guchar *) "\x08\x9c\x3e\x7f\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14" },
{ 9, 16, 4, 0, (guchar *) "\x10\xc0\x38\x00\x7c\x00\xfe\x00\xff\x01\xff\x01\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00" },
{ 7, 15, 3, 7, (guchar *) "\x08\x9c\x3e\x7f\x14\x14\x14\x14\x14\x14\x14\x7f\x3e\x1c\x08" },
{ 9, 15, 4, 7, (guchar *) "\x38\xc0\x7c\x00\xfe\x00\xff\x01\xff\x01\x7c\x00\x7c\x00\x7c\x00\x7c\x00\x7c\x00\xff\x01\xff\x01\xfe\x00\x7c\x00\x38\x00" },
{ 15, 16, 10, 0, (guchar *) "\x00\x84\x00\x0e\x00\x1f\x80\x7b\xa0\x7b\x90\x7b\x88\x7b\x88\x7b\x88\x7b\x88\x7b\x8c\x7b\x8e\x7b\xbf\x7b\x18\x11\x00\x1e\x00\x0c" },
{ 16, 16, 11, 0, (guchar *) "\x00\x1c\x00\x3e\x00\x7f\x00\xff\x60\xff\x70\xff\x78\xff\x78\xff\x78\xff\x78\xff\x7c\xff\x7e\xff\x7f\xff\x7e\x7f\x30\x7e\x00\x3c" },
{ 14, 14, 7, 7, (guchar *) "\xff\xc0\x01\x00\x01\x00\x01\x00\xf1\x03\x11\x02\x11\x22\x11\x22\x10\x22\xf0\x23\x00\x24\x00\x28\x00\x30\xc0\x3f" },
{ 16, 16, 8, 8, (guchar *) "\xff\x03\xff\x03\xff\x03\x07\x00\xf7\x0f\xf7\x0f\xf7\xef\x77\xee\x77\xee\xf7\xef\xf0\xef\xf0\xff\x00\xf8\xc0\xff\xc0\xff\xc0\xff" },
{ 16, 16, 6, 7, (guchar *) "\x04\x08\x08\x04\x08\x04\x10\x02\x10\x02\xe1\xe1\xe6\x19\xf8\x07\xf8\x07\xe6\x19\xe1\xe1\x10\x02\x10\x02\x08\x04\x08\x04\x04\x08" },
{ 16, 16, 6, 7, (guchar *) "\x06\x18\x0c\x0c\x08\x04\x18\x06\xf1\x83\xf3\xf3\xf6\x3b\xfc\x0f\xfc\x07\xf6\x1f\xf3\xf3\xf1\x83\x18\x02\x18\x06\x0c\x0c\x06\x18" },
{ 11, 16, 9, 2, (guchar *) "\x00\xe6\x80\x00\x2c\x06\x9e\x00\x16\x06\x3f\x00\x21\x00\x27\x00\x25\x00\x27\x00\x25\x00\x27\x00\x27\x00\x21\x00\x21\x00\x3f\x00" },
{ 12, 16, 10, 2, (guchar *) "\x00\x4c\x18\x0d\x7c\x0d\x7c\x0d\x7e\x0d\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00" },
{ 15, 16, 7, 7, (guchar *) "\x80\x80\x40\x01\x40\x01\x40\x01\x20\x02\x20\x02\x20\x02\x9c\x1c\x03\x60\x1c\x1c\x90\x04\x48\x09\x24\x12\x14\x14\x0c\x18\x04\x10" },
{ 16, 16, 7, 7, (guchar *) "\x80\x00\xc0\x01\xc0\x01\x60\x03\x60\x03\x30\x06\x38\x1e\x9f\x7c\x03\xe0\x1f\x7c\x9c\x1c\xcc\x19\x66\x33\x36\x36\x1e\x3c\x0e\x38" },
{ 15, 13, 7, 6, (guchar *) "\xc0\x81\xf0\x07\x38\x0e\x0c\x18\x06\x30\x83\x60\x43\x61\x83\x60\x06\x30\x0c\x18\x38\x0e\xf0\x07\xc0\x01" },
{ 16, 14, 7, 7, (guchar *) "\xe0\x03\xf0\x07\xf8\x0f\x3c\x1e\x0e\x38\x87\x70\xc3\xe1\x63\xe3\xc3\xe1\x87\x70\x0e\x38\x3c\x1e\xf8\x0f\xe0\x03" },
{ 13, 13, 6, 6, (guchar *) "\x40\xe0\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\xff\x1f\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00" },
{ 15, 15, 7, 7, (guchar *) "\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xff\x7f\xff\x7f\xff\x7f\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01" },
{ 14, 14, 0, 0, (guchar *) "\x03\xc0\x0f\x00\x3e\x00\xfe\x00\xfc\x03\xfc\x0f\xf8\x00\xf8\x00\x30\x01\x30\x02\x20\x04\x20\x08\x00\x10\x00\x20" },
{ 16, 16, 1, 1, (guchar *) "\x07\x00\x1f\x00\x7f\x00\xfe\x01\xfe\x07\xfc\x3f\xfc\x3f\xf8\x3f\xf8\x03\xf0\x07\xf0\x0e\xe0\x1c\xe0\x38\xe0\x70\x00\xe0\x00\xc0" },
{ 14, 14, 0, 0, (guchar *) "\xff\xff\xff\x3f\x03\x00\x03\x00\x03\x00\xe3\x0f\x63\x00\xa3\x00\x23\x01\x23\x02\x23\x04\x23\x08\x03\x00\x03\x00" },
{ 16, 16, 1, 1, (guchar *) "\xff\xff\xff\xff\xff\xff\xff\xff\x0f\x00\xef\x3f\xef\x3f\xef\x3f\xef\x03\xef\x07\xef\x0e\xef\x1c\xef\x38\xef\x30\x0f\x00\x0f\x00" },
{ 14, 14, 13, 0, (guchar *) "\xff\xff\xff\x3f\x00\x30\x00\x30\x00\x30\xfc\x31\x80\x31\x40\x31\x20\x31\x10\x31\x08\x31\x04\x31\x00\x30\x00\x30" },
{ 16, 16, 14, 1, (guchar *) "\xff\xff\xff\xff\xff\xff\xff\xff\x00\xf0\xfc\xf7\xfc\xf7\xfc\xf7\xc0\xf7\xe0\xf7\x70\xf7\x38\xf7\x1c\xf7\x0c\xf7\x00\xf0\x00\xf0" },
{ 13, 14, 6, 0, (guchar *) "\xff\xff\xff\x1f\x00\x00\x40\x00\xe0\x00\x50\x01\x48\x02\x44\x04\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00" },
{ 15, 16, 7, 1, (guchar *) "\xff\x7f\xff\x7f\xff\x7f\xff\x7f\xc0\x01\xe0\x03\xf0\x07\xf8\x0f\xdc\x1d\xcc\x19\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01" },
{ 14, 10, 7, 0, (guchar *) "\xff\xff\xff\x3f\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00\xc0\x00" },
{ 16, 12, 8, 1, (guchar *) "\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03" },
{ 7, 16, 3, 0, (guchar *) "\x88\x80\x1c\x3e\x7f\x77\x7f\x3e\x1c\x08\x5d\x6b\x49\x41\x41\x41" },
{ 9, 16, 4, 0, (guchar *) "\x38\x40\x38\x00\x7c\x00\xfe\x00\xff\x01\xff\x01\xff\x01\xfe\x00\x7c\x00\xba\x00\xff\x01\xff\x01\xff\x01\xd7\x01\xd7\x01\xc7\x01" },
{ 10, 10, 0, 0, (guchar *) "\xff\xe3\xff\x03\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00" },
{ 12, 12, 1, 1, (guchar *) "\xff\x4f\xff\x0f\xff\x0f\xff\x0f\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00" },
{ 14, 14, 7, 2, (guchar *) "\x88\xc4\x20\x0a\xc9\x32\xf2\x09\x4c\x06\x43\x18\x40\x00\x40\x00\x40\x00\x40\x00\x40\x00\x40\x01\x40\x01\x80\x00" },
{ 16, 16, 8, 2, (guchar *) "\xe8\x76\xfb\xdf\xfd\x3f\xfe\xff\xff\x3f\xff\xff\xcf\x79\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x07\xc0\x07\xc0\x07\xc0\x07\x80\x03" },
{ 10, 10, 9, 0, (guchar *) "\xff\xe3\xff\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03\x00\x03" },
{ 12, 12, 10, 1, (guchar *) "\xff\x4f\xff\x0f\xff\x0f\xff\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f\x00\x0f" },
{ 16, 16, 15, 9, (guchar *) "\xf8\x07\xf8\x07\xf8\x07\xfc\x0f\x86\x18\x83\x30\x81\xe0\xc1\xe1\xc1\xe1\x21\xe0\x13\x30\x06\x18\xfc\x0f\xf8\x07\xf8\x07\xf8\x07" },
{ 16, 16, 15, 9, (guchar *) "\xfc\x0f\xfc\x0f\xfc\x0f\xfe\x1f\xff\x3f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x3f\xfe\x1f\xfc\x0f\xfc\x0f\xfc\x0f" },
{ 7, 14, 3, 7, (guchar *) "\xf7\x9c\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x1c\x77" },
{ 9, 16, 4, 8, (guchar *) "\xef\x41\xff\x01\xff\x01\x7c\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x7c\x00\xff\x01\xff\x01\xef\x01" },
};

View File

@ -60,6 +60,9 @@
#ifdef GDK_RENDERING_VULKAN
#include "vulkan/gskvulkanrenderer.h"
#endif
#ifdef GDK_WINDOWING_MACOS
#include <gdk/macos/gdkmacos.h>
#endif
typedef struct
{
@ -555,6 +558,10 @@ get_renderer_for_backend (GdkSurface *surface)
if (GDK_IS_BROADWAY_SURFACE (surface))
return GSK_TYPE_BROADWAY_RENDERER;
#endif
#ifdef GDK_WINDOWING_MACOS
if (GDK_IS_MACOS_SURFACE (surface))
return GSK_TYPE_GL_RENDERER;
#endif
return G_TYPE_INVALID;
}

View File

@ -1053,6 +1053,12 @@ if cc.has_header('langinfo.h')
endforeach
endif
# Maintain compatibility with autotools
gtk_ldflags = []
if os_darwin
gtk_ldflags += [ '-compatibility_version 1', '-current_version 1.0', ]
endif
# Library
libgtk = library('gtk-4',
soversion: gtk_soversion,
@ -1062,7 +1068,7 @@ libgtk = library('gtk-4',
include_directories: [confinc, gdkinc, gskinc, gtkinc],
dependencies: gtk_deps + [libgtk_css_dep, libgdk_dep, libgsk_dep],
link_with: [libgtk_css, libgdk, libgsk, ],
link_args: common_ldflags,
link_args: common_ldflags + gtk_ldflags,
install: true)
gtk_dep_sources = [gtkversion, gtktypebuiltins_h]

Some files were not shown because too many files have changed in this diff Show More