Objective-J and Cappuccino and CGRect - cappuccino

I'm quite new to objective-j and the framework so I was attempting to drill down and understand some code, but I'm getting lost with the object (or struct) CGRect.
Here is the full documentation: Cappuccino
Ok, now I'm drilling down and I try to learn how the CPView class works: CPView.j
Now, I see CGRect objects (or structures) everywhere and I simply CANNOT for the life me figure out where CGRect is defined. How does this work? I feel like I am missing something.
The closest thing I've found is CGGeometry.j and CGGeometry.h, but still no CGRect structure or object is defined.
Can someone help me out? How is it possible to instantiate a CGRect struct or object and where is it defined? What does it contain? etc etc...
I know that the main way to create a CGRect is to use the CGRectMake function as stated here.
I just don't feel like I have a grasp on how this is working.
Thank you.
Update:
After looking at the code some more: line 23, line 30, and line 37, seem to look kinda like JavaScript object descriptions. Is this correct? I'm not sure... is whatever that is translating these .j files aware of what a CGRect is already? Is this the reason we can use (CGRect) type castes and objects? CGRects seem like they are not the same as any other object I've seen used so far, and I'd like to know why :).
Thanks, again.
00023 #define _CGPointMake(x_, y_) { x:x_, y:y_ }
00024 #define _CGPointMakeCopy(aPoint) _CGPointMake(aPoint.x, aPoint.y)
00025 #define _CGPointMakeZero() _CGPointMake(0.0, 0.0)
00026
00027 #define _CGPointEqualToPoint(lhsPoint, rhsPoint) (lhsPoint.x == rhsPoint.x && lhsPoint.y == rhsPoint.y)
00028 #define _CGStringFromPoint(aPoint) ("{" + aPoint.x + ", " + aPoint.y + "}")
00029
00030 #define _CGSizeMake(width_, height_) { width:width_, height:height_ }
00031 #define _CGSizeMakeCopy(aSize) _CGSizeMake(aSize.width, aSize.height)
00032 #define _CGSizeMakeZero() _CGSizeMake(0.0, 0.0)
00033
00034 #define _CGSizeEqualToSize(lhsSize, rhsSize) (lhsSize.width == rhsSize.width && lhsSize.height == rhsSize.height)
00035 #define _CGStringFromSize(aSize) ("{" + aSize.width + ", " + aSize.height + "}")
00036
00037 #define _CGRectMake(x, y, width, height) { origin: _CGPointMake(x, y), size: _CGSizeMake(width, height) }

The short answer is yes, CGRects are unlike other Cappuccino objects. CGRects are not CPObjects but simply Javascript objects with x, y, width and height members. When you create one, such as with CGRectMake, you're actually invoking a simple function which looks something like this:
function CGRectMake(_x, _y, _width, _height)
{
return {
origin: { x:_x, y:_y },
size: { width: _width, height: _height }
};
}
The declarations you found are the macros which Cappuccino itself uses to inline the CGRectMake function for better performance. The macros are used at the end of the day to actually define the exported CGRectMake function used in your own code (which is why my snippet above is merely an approximation.)

Related

Toggling NSWindow level for "always on top" behaviour

I have a simple single-window application with a menu item that allows users to have the NSWindow appear always on top.
My function looks like this:
#IBAction func changeAlwaysOnTop(sender: AnyObject) {
if (alwaysOnTopMenuItem.state == NSOnState) {
alwaysOnTopMenuItem.state = NSOffState;
window.level = kCGNormalWindowLevelKey;
} else {
alwaysOnTopMenuItem.state = NSOnState;
window.level = kCGStatusWindowLevelKey;
}
}
Turning "Always on Top" on works well - the window floats above all other applications as it should. However, when the option is turned off, the window continues to float above all other windows, as if window.level = kCGNormalWindowLevelKey; isn't actually doing anything.
I've tried different window levels, and I've tried ordering the window out and back in again. The window continues to float above all others.
How can I set the window back to normal after setting the level to kCGNormalWindowLevelKey?
Edit: the following Objective C code works just fine:
- (IBAction)changeOnTop:(id)sender {
if (self.onTopMenuItem.state == NSOnState) {
self.onTopMenuItem.state = NSOffState;
self.window.level = NSNormalWindowLevel;
} else {
self.onTopMenuItem.state = NSOnState;
self.window.level = NSStatusWindowLevel;
}
}
You are using the wrong values for the level. You are using the keys by which window levels are looked up.
First, since you're using Cocoa, you should use the Cocoa constants for the window level: NSNormalWindowLevel and NSStatusWindowLevel.
If you look at the definitions of those constants, you'll find:
#define NSNormalWindowLevel kCGNormalWindowLevel
#define NSStatusWindowLevel kCGStatusWindowLevel
Notice the lack of the word "Key" on the end of those kCG... constants. If you then look up how those constants are defined, you'll find:
#define kCGNormalWindowLevel \
CGWindowLevelForKey(kCGNormalWindowLevelKey)
#define kCGStatusWindowLevel \
CGWindowLevelForKey(kCGStatusWindowLevelKey)
So, the values you used are keys that are passed to CGWindowLevelForKey() to get the actual level.
This works for me, and looks a bit nicer! (Swift 4)
window.level = .floatingWindowLevel
This worked for me in Swift 4.2.
override func viewDidAppear() {
super.viewDidAppear()
view.window?.level = .floating
}

Pango + Cairo; is there an existing approach for handling <img> style tags in text?

Pango syntax supports some text only markup. As far as i can see this does not extend to embedding images as well.
Looking around I cannot find much in the way of an existing implementation, but i havent done pango+cairo work before so i might be missing the obvious community for it.
As far as i can tell a reasonable approach would be to just analyse a string, pull out any tags, create cairo images, and then modify the pango layout around them accordingly.
It also seems like something someone might have done before.
Im specifically looking for an answer on these questions:
Does pango+cairo already solve this and I have just misread the docs?
Has something like this been done before, and where is a reference?
Is this a reasonable approach, or should i try something else, and what?
(also note i am using ruby, so that may affect my options)
I've been through the source of the markup parser and it does not allow for "shape" attributes (the way Pango almost incorporates graphics) but it is possible to do it "by hand".
Since there is absolutely no example code on the Web, here's Pango/Cairo/Images 101.
For a simple demo, I created an 800x400 window, added a GtkDrawingArea and connected up the "draw" signal. Before entering the main program loop, I initialized it with the following code:
PangoLayout *Pango;
void init_drawingArea (GtkWidget *pWidget)
{
cairo_surface_t *pImg = cairo_image_surface_create_from_png ("linux.png");
PangoRectangle r = {0, 0, PANGO_SCALE * cairo_image_surface_get_width (pImg),
PANGO_SCALE * cairo_image_surface_get_height(pImg)};
PangoContext *ctxt = gtk_widget_get_pango_context (pWidget);
PangoAttrList *attList = pango_attr_list_new();
PangoAttribute *attr;
Pango = pango_layout_new (ctxt);
pango_cairo_context_set_shape_renderer (ctxt, render, NULL, NULL);
pango_layout_set_text (Pango, pszLorem, -1);
pango_layout_set_width(Pango, PANGO_SCALE * 800);
attr = pango_attr_shape_new_with_data(&r, &r, pImg, NULL, NULL);
attr->start_index = 0; attr->end_index = 1;
pango_attr_list_insert (attList, attr);
attr = pango_attr_shape_new_with_data(&r, &r, pImg, NULL, NULL);
attr->start_index = 152; attr->end_index = 153;
pango_attr_list_insert (attList, attr);
pango_layout_set_attributes (Pango, attList);
}
The context's shape renderer is set to render () and a PangoLayout is created and initialized. It then creates 2 shape attributes, sets the user data to a cairo surface which we populate from a png file and applies the attributes to characters 0 and 152 of the text.
The "draw" signal processing is straightforward.
gboolean onDraw (GtkWidget *pWidget, cairo_t *cr, gpointer user_data)
{
pango_cairo_show_layout (cr, Pango);
return 1;
}
and the render () PangoCairoShapeRenderFunc function is called as needed:
void render (cairo_t *cr, PangoAttrShape *pShape, gboolean do_path, gpointer data)
{
cairo_surface_t *img = (cairo_surface_t *)pShape->data;
double dx, dy;
cairo_get_current_point(cr, &dx, &dy);
cairo_set_source_surface(cr, img, dx, dy);
cairo_rectangle (cr, dx, dy, pShape->ink_rect.width/PANGO_SCALE,
pShape->ink_rect.height/PANGO_SCALE);
cairo_fill(cr);
}
Taking the current point from cairo, it draws a rectangle and fills it with the image.
And that's pretty much all it does. Images were added as an afterthought and it shows. They are subject to the same rules as any other glyph so they are limited to the equivalent of CSS's display: inline.
I've put the code up at http://immortalsofar.com/PangoDemo/ if anyone wants to play with it. Me, I arrived here trying to get around GtkTextBuffer's limitations. Guess I'll just have to go deeper.

NSOpenGL profile version 3_2Core

When I add NSOpenGLProfileVersion3_2Core to the attributes pixelformat variable is nil, but when i remove it pixel format gets allocated. I dont get what is the problem : (
GLuint attributes[] = {
NSOpenGLProfileVersionLegacy,
NSOpenGLProfileVersion3_2Core,
NSOpenGLPFAWindow,
NSOpenGLPFAColorSize, 24,
NSOpenGLPFAAlphaSize, 8,
NSOpenGLPFAAccelerated,
NSOpenGLPFADoubleBuffer,
0
};
_pixelformat = [[NSOpenGLPixelFormat alloc]
initWithAttributes:
(NSOpenGLPixelFormatAttribute *) attributes];
if (_pixelformat == nil){
NSLog(#"No valid OpenGL pixel format");
exit(0);
}
NSLog(#"Have a valid pixel format");
The result is "No valid OpenGL pixel format."
genpfault has the right idea, but neither of those attributes is valid on its own. That is to say, they are not boolean attributes/flags.
You need to match the constant with an appropriate attribute name.
Replace this code:
GLuint attributes[] = {
NSOpenGLProfileVersionLegacy,
NSOpenGLProfileVersion3_2Core,
[...]
With this:
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFAOpenGLProfile, (NSOpenGLPixelFormatAttribute)NSOpenGLProfileVersion3_2Core,
[...]
I also took the liberty of correcting your use of typedefs. NSOpenGLPixelFormatAttribute is defined as uint32_t, while OpenGL requires GLuint be an unsigned integer type at least 32-bits wide. OpenGL does not forbid GLuint from being implemented using something like uint64_t in the future.
Use the correct API-defined typedef whenever possible.
solved. need to remove NSOpenGLPFAWindow attribute.
NSOpenGLProfileVersionLegacy,
NSOpenGLProfileVersion3_2Core,
Pick one. You can't have a context that is somehow both Core and not-Core at the same time.

How to get multitouch to work in QGraphicsView, Qt 5.0.2 in Windows 8

I am struggling with getting multi-touch to work on a couple of QWidgets that I have added to a QGraphicsView. I have created a subclass of QWidget in which I set up a QGraphicsScene and QGraphicsView. This is my (test) subclass of QWidget:
#include "qttest1.h"
#include <QtWidgets>
#include <QTouchEvent>
qttest1::qttest1(QWidget *parent)
: QWidget(parent)
{
setEnabled(true);
if(!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings))
setAttribute(Qt::WA_NativeWindow);
setAttribute(Qt::WA_AcceptTouchEvents);
scene = new QGraphicsScene(this);
scene->setSceneRect(0, 0, 1920, 1080);
graphicsView = new QGraphicsView(scene, this);
graphicsView->setRenderHints(QPainter::Antialiasing);
graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
graphicsView->setAttribute(Qt::WA_AcceptTouchEvents);
graphicsView->viewport()->setAttribute(Qt::WA_AcceptTouchEvents);
QBoxLayout *layout = new QVBoxLayout;
layout->addWidget(graphicsView);
setLayout(layout);
}
qttest1::~qttest1() {}
void qttest1::showGraphics()
{
for(int i = 0; i < 10; i++)
{
Dial *dial = new QDial();
dial->move(i * 120 + 50, 200);
dial->resize(120, 120);
dial->setAttribute(Qt::WA_AcceptTouchEvents);
QGraphicsProxyWidget *proxy = scene->addWidget(dial);
proxy->setAcceptTouchEvents(true);
}
}
This is my main:
int main(int argc, char **argv)
{
QApplication app(argc, argv);
app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
QRect rect = app.desktop()->screenGeometry();
qttest1 test;
test.resize(rect.width(), rect.height());
test.showFullScreen();
test.showGraphics();
return app.exec();
}
I know the code isn't pretty and probably leaking a bit, but the point is to try to get multi-touch to work.
I can see and use every kind of widget I add to the scene, but as soon as I touch a dial it swallows every touch that comes after the first. Which makes the dial jump between several positions. What I want is that every dial (or any type of widget) can be used individually and at the same time. I am using QT 5.0.2, Windows 8 with a monitor that supports up to 10 touches.
The Qt docs state : -
Reimplement QWidget::event() or QAbstractScrollArea::viewportEvent()
for widgets and QGraphicsItem::sceneEvent() for items in a graphics
view to receive touch events.
With that, I believe that you need to handle the QEvent::TouchBegin, QEvent::TouchUpdate and QEvent::TouchEnd events, which I don't see in the code you've posted.
Qt may handle the first touch for you, but it's not going to know what you want to do with the second, third, fourth etc. simultaneous touches. For example, you may want your app to do any of the following with the second touch moving: -
1) Rotate the object that the first item is over
2) Scale the object that the first item is over
3) Select the second item
4) Translate the view
5) etc.
So, you need to handle the consecutive touches to do what you want it to do. Also, you may want to look at Gestures in Qt.

Which API can be used to _capture_ the mouse when moving OS X "Carbon" windows?

On request I have implemented support for moving an OS X window by dragging it using an area within the content part of the window, i.e replicating the drag and move functionality of the title bar but in another area.
The problem I have yet to resolve is the fact that if the user drags the mouse quickly it can leave the window area and then no more mouse move events are received.
On windows this type of problem can simply be fixed by calling the win32 method SetCapture(), what's the corresponding OSX method?
This application is a cross platform C++ application using Carbon for the OS X specific parts. (And yes, I know all about the Cocoa benefits but this is an older code base and there no time nor money for a Cocoa port at this point in time.)
I have found Carbon API methods like for example TrackMouseLocation() but can't really see how I could use them for this application. In listing 2-7 here http://developer.apple.com/legacy/mac/library/documentation/Carbon/Conceptual/Carbon_Event_Manager/Tasks/CarbonEventsTasks.html
the mouse is captured but the problem is that TrackMouseLocation() blocks waiting for input. Blocking is something this application can not do since it also host a flash player that must be called many times per second.
The protototype I have assembled when trying to figure this out basically looks like this:
switch(GetEventKind(inEvent))
{
case kEventMouseDown:
// A silly test to make parts of the window border "draggable"
dragging = local_loc.v < 25 || local_loc.h < 25;
last_screen_loc = screen_loc;
break;
case kEventMouseUp:
dragging = false;
break;
case kEventMouseMoved:
break;
case kEventMouseDragged:
if (dragging) {
Rect rect;
GetWindowBounds (windowRef, kWindowContentRgn, &rect);
int dx = screen_loc.h - last_screen_loc.h;
int dy = screen_loc.v - last_screen_loc.v;
rect.left += dx;
rect.right += dx;
rect.top += dy;
rect.bottom += dy;
SetWindowBounds (windowRef, kWindowContentRgn, &rect);
}
last_screen_loc = screen_loc;
break;
Any ideas appreciated?
I feel you should track mouse in Window as well as out of window. Following code should solve your problem,
EventHandlerRef m_ApplicationMouseDragEventHandlerRef;
EventHandlerRef m_MonitorMouseDragEventHandlerRef;
{
OSStatus ErrStatus;
static const EventTypeSpec kMouseDragEvents[] =
{
{ kEventClassMouse, kEventMouseDragged }
};
ErrStatus = InstallEventHandler(GetEventMonitorTarget(), NewEventHandlerUPP(MouseHasDragged), GetEventTypeCount(kMouseDragEvents), kMouseDragEvents, this, &m_MonitorMouseDragEventHandlerRef);
ErrStatus = InstallApplicationEventHandler(NewEventHandlerUPP(MouseHasDragged), GetEventTypeCount(kMouseDragEvents), kMouseDragEvents, this, &m_ApplicationMouseDragEventHandlerRef);
return true;
}
//implement these functions
OSStatus MouseHasDragged(EventHandlerCallRef inCaller, EventRef inEvent, void *pUserData){}
Hope it helps!!
I Hope It Help´s you too:
// Get Mouse Position --> WAY 1
printf("Get Mouse Position Way 1\n");
HICoordinateSpace space = 2;
HIGetMousePosition(space, NULL, &point);
printf("Mouse Position: %.2f %.2f \n", point.x, point.y);
// Get Mouse Position --> WAY 2
printf("Get Mouse Position Way 2\n");
CGEventRef ourEvent = CGEventCreate(NULL);
point = CGEventGetLocation(ourEvent);
printf("Mouse Position: %.2f, y = %.2f \n", (float)point.x, (float)point.y);
I´m looking for the way to get a WindowPart Reference at a certain location (over all windows of all aplications)
Certain methods in Carbon doesn´t work, always return 0 as a windowRef... Any ideas?
You could also try just calling DragWindow in response to a click in your window's content area. I don't think you need to implement the dragging yourself.

Resources