Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit 271348d

Browse files
author
Fraser J. Gordon
committed
[[ Native Widgets ]] Initial implementation for Linux/X11
Doesn't work properly atm - edit mode is broken in some cases, layering does not work. Probably many other things too...
1 parent da645d6 commit 271348d

4 files changed

Lines changed: 342 additions & 1 deletion

File tree

engine/Makefile.kernel

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ SOURCES=\
7777
exec-interface-vclip.cpp exec-keywords.cpp exec-legacy.cpp exec-dialog.cpp exec-strings-chunk.cpp \
7878
syntax.cpp \
7979
foundation-legacy.cpp legacy_spec.cpp \
80-
sysunxthreads.cpp, stacktile.cpp
80+
sysunxthreads.cpp, stacktile.cpp \
81+
native-layer.cpp native-layer-x11.cpp \
82+
widget.cpp widget-events.cpp
8183

8284
linuxstubs.cpp: src/linux.stubs ../util/weak_stub_maker.pl
8385
# ../prebuilt/bin/Revolution.lnx "../tools/weak_stub_maker.lc" <./src/linux.stubs >./src/linuxstubs.cpp

engine/src/linux.stubs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,8 @@ gdk libgdk-x11-2.0.so.0
297297
gdk_window_set_skip_pager_hint: (pointer, integer) -> ()
298298
gdk_window_constrain_size: (pointer, integer, integer, integer, pointer, pointer) -> ()
299299
gdk_window_unmaximize: (pointer) -> ()
300+
301+
gdk_window_reparent: (pointer, pointer, integer, integer) -> ()
300302

301303
gdk_pixbuf libgdk_pixbuf-2.0.so.0
302304
gdk_pixbuf_get_pixels: (pointer) -> (pointer)
@@ -461,6 +463,28 @@ gtk libgtk-x11-2.0.so.0
461463
gtk_im_context_set_use_preedit: (pointer, integer) -> ()
462464
gtk_im_context_get_preedit_string: (pointer, pointer, pointer, pointer) -> ()
463465

466+
gtk_widget_set_size_request: (pointer, integer, integer) -> ()
467+
gtk_socket_get_type: () -> (integer)
468+
gtk_socket_new: () -> (pointer)
469+
gtk_fixed_put: (pointer, pointer, integer, integer) -> ()
470+
gtk_socket_add_id: (pointer, integer) -> ()
471+
gtk_widget_hide: (pointer) -> ()
472+
gtk_widget_show: (pointer) -> ()
473+
gtk_fixed_move: (pointer, pointer, integer, integer) -> ()
474+
gtk_fixed_get_type: () -> (integer)
475+
gtk_bin_get_child: (pointer) -> (pointer)
476+
gtk_widget_set_realized: (pointer, integer) -> ()
477+
gtk_widget_set_window: (pointer, pointer) -> ()
478+
gtk_socket_get_plug_window: (pointer) -> (pointer)
479+
gtk_widget_set_parent_window: (pointer, pointer) -> ()
480+
gtk_widget_get_window: (pointer) -> (pointer)
481+
gtk_socket_get_id: (pointer) -> (integer)
482+
483+
gtk_plug_new: (integer) -> (pointer)
484+
gtk_plug_get_type: () -> (integer)
485+
gtk_plug_get_id: (pointer) -> (integer)
486+
gtk_widget_unparent: (pointer) -> ()
487+
464488
gtk_print_dialog libgtk-x11-2.0.so.0
465489
gtk_print_unix_dialog_new: (pointer, pointer) -> (pointer)
466490
gtk_print_unix_dialog_get_selected_printer: (pointer) -> (pointer)

engine/src/native-layer-x11.cpp

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
/* Copyright (C) 2014 Runtime Revolution Ltd.
2+
3+
This file is part of LiveCode.
4+
5+
LiveCode is free software; you can redistribute it and/or modify it under
6+
the terms of the GNU General Public License v3 as published by the Free
7+
Software Foundation.
8+
9+
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
10+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
16+
17+
#include "prefix.h"
18+
19+
#include "globdefs.h"
20+
#include "filedefs.h"
21+
#include "objdefs.h"
22+
#include "parsedef.h"
23+
24+
#include "execpt.h"
25+
#include "util.h"
26+
#include "mcerror.h"
27+
#include "sellst.h"
28+
#include "stack.h"
29+
#include "card.h"
30+
#include "image.h"
31+
#include "widget.h"
32+
#include "param.h"
33+
#include "osspec.h"
34+
#include "cmds.h"
35+
#include "scriptpt.h"
36+
#include "hndlrlst.h"
37+
#include "debug.h"
38+
#include "redraw.h"
39+
#include "font.h"
40+
#include "chunk.h"
41+
#include "graphicscontext.h"
42+
#include "objptr.h"
43+
44+
#include "globals.h"
45+
#include "context.h"
46+
47+
#include "lnxdc.h"
48+
#include "graphicscontext.h"
49+
50+
#include "native-layer-x11.h"
51+
52+
#include <gdk/gdk.h>
53+
#include <gtk/gtk.h>
54+
55+
56+
MCNativeLayerX11::MCNativeLayerX11(MCWidget* p_widget) :
57+
m_widget(p_widget),
58+
m_socket(NULL)
59+
{
60+
61+
}
62+
63+
MCNativeLayerX11::~MCNativeLayerX11()
64+
{
65+
if (m_socket != NULL)
66+
{
67+
g_object_unref(m_socket);
68+
}
69+
}
70+
71+
void MCNativeLayerX11::OnToolChanged(Tool p_new_tool)
72+
{
73+
if (p_new_tool == T_BROWSE || p_new_tool == T_HELP)
74+
{
75+
// In run mode. Hide the overlay window
76+
gdk_window_hide(m_overlay);
77+
}
78+
else
79+
{
80+
// In edit mode. Put a transparent overlay over the main window
81+
gdk_window_show(m_overlay);
82+
}
83+
}
84+
85+
void MCNativeLayerX11::OnOpen()
86+
{
87+
// Unhide the widget, if required
88+
if (isAttached() && m_widget->getopened() == 1)
89+
doAttach();
90+
}
91+
92+
void MCNativeLayerX11::OnClose()
93+
{
94+
if (isAttached() && m_widget->getopened() == 0)
95+
doDetach();
96+
}
97+
98+
void MCNativeLayerX11::OnAttach()
99+
{
100+
m_attached = true;
101+
doAttach();
102+
}
103+
104+
void MCNativeLayerX11::doAttach()
105+
{
106+
if (m_socket == NULL)
107+
{
108+
// Create a new GTK socket to deal with the XEMBED protocol
109+
m_socket = GTK_SOCKET(gtk_socket_new());
110+
111+
// Create a new GTK window to hold the socket
112+
MCRectangle t_rect;
113+
t_rect = m_widget->getrect();
114+
m_child_window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_POPUP));
115+
gtk_widget_set_parent_window(GTK_WIDGET(m_child_window), getStackGdkWindow());
116+
gtk_widget_realize(GTK_WIDGET(m_child_window));
117+
gdk_window_reparent(gtk_widget_get_window(GTK_WIDGET(m_child_window)), getStackGdkWindow(), t_rect.x, t_rect.y);
118+
119+
// Add the socket to the window
120+
gtk_container_add(GTK_CONTAINER(m_child_window), GTK_WIDGET(m_socket));
121+
122+
// The socket needs to be realised before going any further or any
123+
// operations on it will fail.
124+
gtk_widget_realize(GTK_WIDGET(m_socket));
125+
126+
// Show the socket (we'll control visibility at the window level)
127+
gtk_widget_show(GTK_WIDGET(m_socket));
128+
129+
// Create an overlay window to intercept events in edit mode
130+
MCScreenDC* t_screen = (MCScreenDC*)MCscreen;
131+
GdkWindowAttr gdkwa;
132+
guint gdk_valid_wa;
133+
gdk_valid_wa = GDK_WA_X|GDK_WA_Y|GDK_WA_VISUAL;
134+
gdkwa.x = t_rect.x;
135+
gdkwa.y = t_rect.y;
136+
gdkwa.width = t_rect.width;
137+
gdkwa.height = t_rect.height;
138+
gdkwa.wclass = GDK_INPUT_ONLY;
139+
gdkwa.window_type = GDK_WINDOW_CHILD;
140+
gdkwa.visual = t_screen->getvisual();
141+
gdkwa.colormap = t_screen->getcmap();
142+
gdkwa.event_mask = 0; // Don't care about any events
143+
m_overlay = gdk_window_new(getStackGdkWindow(), &gdkwa, gdk_valid_wa);
144+
gdk_window_show(m_overlay);
145+
146+
// TESTING
147+
148+
/*GtkPlug *t_plug = GTK_PLUG(gtk_plug_new(0));
149+
gtk_widget_realize(GTK_WIDGET(t_plug));
150+
m_widget_xid = gtk_plug_get_id(t_plug);
151+
GtkButton* t_button = GTK_BUTTON(gtk_button_new_with_label("Native Button"));
152+
gtk_container_add(GTK_CONTAINER(t_plug), GTK_WIDGET(t_button));
153+
gtk_widget_show(GTK_WIDGET(t_button));
154+
gtk_widget_show(GTK_WIDGET(t_plug));*/
155+
}
156+
157+
// Attach the X11 window to this socket
158+
if (gtk_socket_get_plug_window(m_socket) == NULL)
159+
gtk_socket_add_id(m_socket, m_widget_xid);
160+
//fprintf(stderr, "XID: %#u\n", gtk_socket_get_id(m_socket));
161+
162+
// Act as if there were a re-layer to put the widget in the right place
163+
doRelayer();
164+
165+
// Restore the visibility state of the widget (in case it changed due to a
166+
// tool change while on aother card - we don't get a message then)
167+
if ((m_widget->getflags() & F_VISIBLE) && !m_widget->inEditMode())
168+
gtk_widget_hide(GTK_WIDGET(m_socket));
169+
else
170+
gtk_widget_show(GTK_WIDGET(m_socket));
171+
}
172+
173+
void MCNativeLayerX11::OnDetach()
174+
{
175+
m_attached = false;
176+
doDetach();
177+
}
178+
179+
void MCNativeLayerX11::doDetach()
180+
{
181+
// We don't really detach; just stop showing the socket
182+
gtk_widget_hide(GTK_WIDGET(m_socket));
183+
}
184+
185+
void MCNativeLayerX11::OnPaint(MCDC* p_dc, const MCRectangle& p_dirty)
186+
{
187+
// We can't do paint on demand for X11 windows; just let the windowing
188+
// system deal with it the normal way.
189+
}
190+
191+
void MCNativeLayerX11::OnGeometryChanged(const MCRectangle& p_old_rect)
192+
{
193+
// Move the overlay window first, to ensure events don't get stolen
194+
MCRectangle t_rect;
195+
t_rect = m_widget->getrect();
196+
gdk_window_move_resize(m_overlay, t_rect.x, t_rect.y, t_rect.width, t_rect.height);
197+
198+
// Resize by adjusting the widget's containing GtkWindow
199+
gdk_window_move_resize(gtk_widget_get_window(GTK_WIDGET(m_child_window)), t_rect.x, t_rect.y, t_rect.width, t_rect.height);
200+
201+
// Resize the socket
202+
gdk_window_move_resize(gtk_widget_get_window(GTK_WIDGET(m_socket)), 0, 0, t_rect.width, t_rect.height);
203+
204+
// Update the contained window too
205+
GdkWindow* t_remote;
206+
t_remote = gtk_socket_get_plug_window(m_socket);
207+
if (t_remote != NULL)
208+
gdk_window_move_resize(t_remote, 0, 0, t_rect.width, t_rect.height);
209+
}
210+
211+
void MCNativeLayerX11::OnVisibilityChanged(bool p_visible)
212+
{
213+
if (p_visible)
214+
gtk_widget_show(GTK_WIDGET(m_child_window));
215+
else
216+
gtk_widget_hide(GTK_WIDGET(m_child_window));
217+
}
218+
219+
void MCNativeLayerX11::OnLayerChanged()
220+
{
221+
doRelayer();
222+
}
223+
224+
void MCNativeLayerX11::doRelayer()
225+
{
226+
gtk_widget_show(GTK_WIDGET(m_child_window));
227+
}
228+
229+
////////////////////////////////////////////////////////////////////////////////
230+
231+
x11::Window MCNativeLayerX11::getStackX11Window()
232+
{
233+
return x11::gdk_x11_drawable_get_xid(getStackGdkWindow());
234+
}
235+
236+
GdkWindow* MCNativeLayerX11::getStackGdkWindow()
237+
{
238+
return m_widget->getstack()->getwindow();
239+
}
240+
241+
////////////////////////////////////////////////////////////////////////////////
242+
243+
MCNativeLayer* MCWidget::createNativeLayer()
244+
{
245+
return new MCNativeLayerX11(this);
246+
}

engine/src/native-layer-x11.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/* Copyright (C) 2014 Runtime Revolution Ltd.
2+
3+
This file is part of LiveCode.
4+
5+
LiveCode is free software; you can redistribute it and/or modify it under
6+
the terms of the GNU General Public License v3 as published by the Free
7+
Software Foundation.
8+
9+
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
10+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
for more details.
13+
14+
You should have received a copy of the GNU General Public License
15+
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
16+
17+
#ifndef __MC_NATIVE_LAYER_X11__
18+
#define __MC_NATIVE_LAYER_X11__
19+
20+
#include "native-layer.h"
21+
22+
#include <gtk/gtk.h>
23+
24+
namespace x11
25+
{
26+
#include <gdk/gdkx.h>
27+
}
28+
29+
class MCNativeLayerX11 : public MCNativeLayer
30+
{
31+
public:
32+
33+
virtual void OnOpen();
34+
virtual void OnClose();
35+
virtual void OnAttach();
36+
virtual void OnDetach();
37+
virtual void OnPaint(MCDC* p_dc, const MCRectangle& p_dirty);
38+
virtual void OnGeometryChanged(const MCRectangle& p_old_rect);
39+
virtual void OnVisibilityChanged(bool p_visible);
40+
virtual void OnToolChanged(Tool p_new_tool);
41+
virtual void OnLayerChanged();
42+
43+
MCNativeLayerX11(MCWidget*);
44+
~MCNativeLayerX11();
45+
46+
private:
47+
48+
MCWidget* m_widget;
49+
GtkWindow* m_child_window;
50+
GdkWindow* m_overlay;
51+
GtkSocket* m_socket;
52+
x11::Window m_widget_xid;
53+
54+
// Returns the handle for the stack containing this widget
55+
x11::Window getStackX11Window();
56+
GdkWindow* getStackGdkWindow();
57+
58+
// Returns the GtkFixed used for layouts within the stack
59+
GtkFixed* getStackLayout();
60+
61+
// Performs the attach/detach operations
62+
void doAttach();
63+
void doDetach();
64+
65+
// Performs a relayering operation
66+
void doRelayer();
67+
};
68+
69+
#endif // ifndef __MC_NATIVE_LAYER_X11__

0 commit comments

Comments
 (0)