📄 cwindow.cpp
字号:
/*************************************************************************** CWindow.cpp The Window and Form classes (c) 2000-2003 Beno� Minisini <gambas@users.sourceforge.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __CWINDOW_CPP#include <qnamespace.h>#include <qapplication.h>#include <qmenubar.h>#include <qframe.h>#include <qabstractlayout.h>#include <qsizepolicy.h>#include <qtoolbar.h>#include <qworkspace.h>#include <qkeycode.h>#include <qpixmap.h>#include <qbitmap.h>#if QT_VERSION >= 0x030100 #include <qeventloop.h>#endif#include "gambas.h"#include "main.h"#include "CWidget.h"#include "CMenu.h"#include "CWindow.h"#include <X11/Xlib.h>#include <X11/Xatom.h>#include <X11/extensions/shape.h>//#define DEBUG_STATEDECLARE_EVENT(EVENT_Open);DECLARE_EVENT(EVENT_Close);DECLARE_EVENT(EVENT_Activate);DECLARE_EVENT(EVENT_Deactivate);DECLARE_EVENT(EVENT_Move);DECLARE_EVENT(EVENT_Resize);DECLARE_EVENT(EVENT_Show);DECLARE_EVENT(EVENT_Hide);CWINDOW *CWINDOW_Main = NULL;CWINDOW *CWINDOW_Current = NULL;static GB_CLASS CLASS_Workspace = NULL;static GB_CLASS CLASS_Container = NULL;/*************************************************************************** Window manager specific code***************************************************************************/#define MAX_WINDOW_STATE 8static bool _atom_init = false;static Atom _atom_net_wm_state;static Atom _atom_net_wm_state_above;static Atom _atom_net_wm_state_stays_on_top;static Atom _atom_net_wm_state_skip_taskbar;static Atom _window_state[MAX_WINDOW_STATE];static int _window_state_count = 0;static void init_atoms(Display *dpy){ if (_atom_init) return; _atom_net_wm_state = XInternAtom(dpy, "_NET_WM_STATE", True); _atom_net_wm_state_above = XInternAtom(dpy, "_NET_WM_STATE_ABOVE", True); _atom_net_wm_state_stays_on_top = XInternAtom(dpy, "_NET_WM_STATE_STAYS_ON_TOP", True); _atom_net_wm_state_skip_taskbar = XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", True); _atom_init = true;}static void load_window_state(Display *dpy, WId wid){ Atom type; int format; unsigned long length, after; unsigned char *data; init_atoms(dpy); _window_state_count = 0; XGetWindowProperty(dpy, wid, _atom_net_wm_state, 0, 8, False, AnyPropertyType, &type, &format, &length, &after, &data); if (length > 8) length = 8; _window_state_count = length; memcpy(_window_state, data, _window_state_count * sizeof(Atom)); XFree(data);}static void save_window_state(Display *dpy, WId wid){ XChangeProperty(dpy, wid, _atom_net_wm_state, XA_ATOM, 32, PropModeReplace, (unsigned char *)_window_state, _window_state_count);}static bool is_window_state(Atom state){ int i; for (i = 0; i < _window_state_count; i++) { if (_window_state[i] == state) return true; } return false;}static void set_window_state(Atom state){ if (is_window_state(state)) return; if (_window_state_count == MAX_WINDOW_STATE) { qDebug("Too many properties in window"); return; } _window_state[_window_state_count++] = state;}static void clear_window_state(Atom state){ int i; for (i = 0; i < _window_state_count; i++) { if (_window_state[i] == state) { _window_state_count--; for (; i < _window_state_count; i++) _window_state[i] = _window_state[i + 1]; return; } }}void CWINDOW_change_property(QWidget *w, Atom property, bool set){ XEvent e; long mask = (SubstructureRedirectMask | SubstructureNotifyMask); if (!w->isTopLevel()) return; if (w->isVisible()) { e.xclient.type = ClientMessage; e.xclient.message_type = _atom_net_wm_state; e.xclient.display = w->x11Display(); e.xclient.window = w->winId(); e.xclient.format = 32; e.xclient.data.l[0] = set ? 1 : 0; e.xclient.data.l[1] = property; e.xclient.data.l[2] = 0; e.xclient.data.l[3] = 0; e.xclient.data.l[4] = 0; XSendEvent(w->x11Display(), qt_xrootwin(), False, mask, &e); } else { load_window_state(w->x11Display(), w->winId()); if (set) set_window_state(property); else clear_window_state(property); save_window_state(w->x11Display(), w->winId()); }}/*************************************************************************** Window***************************************************************************/BEGIN_METHOD_VOID(CWINDOW_init) CLASS_Workspace = GB.FindClass("Workspace"); CLASS_Container = GB.FindClass("Container");END_METHODBEGIN_METHOD(CWINDOW_new, GB_OBJECT parent) //MyMainWindow *win = new MyMainWindow(window_main ? QMAINWINDOW(window_main) : NULL); MyMainWindow *win = 0; QFrame *frame = 0; QWidget *container; if (MISSING(parent)) { //qDebug("CWINDOW_new: missing parent"); //qDebug("CWINDOW_Main = %p", CWINDOW_Main); //qDebug("CWINDOW_new %p", THIS); win = new MyMainWindow(CWINDOW_Main ? (MyMainWindow *)QWIDGET(CWINDOW_Main) : 0); container = new MyContainer(win); THIS->widget.widget = win; THIS->embedded = false; THIS->window = true; CWIDGET_new(win, (void *)_object, NULL); } else if (GB.Is(VARG(parent), CLASS_Container)) { frame = new MyEmbeddedWindow(CONTAINER(VARG(parent))); container = frame; THIS->widget.widget = frame; THIS->embedded = true; THIS->window = false; CWIDGET_new(frame, (void *)_object, NULL); } else if (GB.Is(VARG(parent), CLASS_Workspace)) { //qDebug(">> CWINDOW_new: workspace"); win = new MyMainWindow(QWIDGET(VARG(parent))); container = new MyContainer(win); THIS->widget.widget = win; //frame = new MyEmbeddedWindow(QWIDGET(VARG(parent))); //container = frame; //FRAME = frame; THIS->embedded = true; THIS->window = true; //CWIDGET_set_flag(THIS, WF_PARENT_GEOMETRY); CWIDGET_new(win, (void *)_object, NULL); //qDebug("<< CWINDOW_new: workspace"); } else { GB.Error("The parent of a Window must be a Container or a Workspace"); return; } THIS->container = container; container->setBackgroundOrigin(QWidget::WindowOrigin); if (frame) { frame->installEventFilter(&CWindow::manager); } else { win->setCentralWidget(container); win->setOpaqueMoving(true); win->installEventFilter(&CWindow::manager); if (!THIS->embedded) { /*if (CWindow::count >= 64) { GB.Error("Too many windows opened"); return; }*/ CWindow::dict.insert(_object, OBJECT(const CWINDOW)); CWindow::count = CWindow::dict.count(); //qDebug("CWindow::count = %d (%p %s)", CWindow::count, _object, THIS->embedded ? "E" : "W"); if (CWINDOW_Main == 0) { //qDebug("CWINDOW_Main -> %p", THIS); CWINDOW_Main = THIS; } } }END_METHODBEGIN_METHOD_VOID(CFORM_new) GB.Attach(_object, _object, "Form"); if (THIS->embedded && !THIS->window) FRAME->show();END_METHODBEGIN_METHOD_VOID(CFORM_main) CWINDOW *form; form = (CWINDOW *)GB.AutoCreate(GB.GetClass(NULL), 0); //GB.New((void **)&form, GB.GetClass(NULL), NULL, NULL); ((MyMainWindow *)form->widget.widget)->showActivate();END_METHODBEGIN_METHOD(CFORM_load, GB_OBJECT parent) if (!MISSING(parent)) { GB.Push(1, GB_T_OBJECT, VARG(parent)); //qDebug("CFORM_load + parent"); } GB.AutoCreate(GB.GetClass(NULL), MISSING(parent) ? 0 : 1);END_METHODBEGIN_METHOD_VOID(CWINDOW_free) //qDebug("CWINDOW_free"); if (THIS->menu) delete THIS->menu; //PICTURE_set(&(window->icon), 0); GB.StoreObject(NULL, (void **)&(THIS->icon)); GB.StoreObject(NULL, (void **)&(THIS->mask)); GB.Unref((void **)&THIS->focus); /*CALL_METHOD_VOID(CWIDGET_delete);*/END_METHODBEGIN_METHOD_VOID(CWINDOW_next) CWINDOW *next; QPtrDictIterator<CWINDOW> *iter = ENUM(QPtrDictIterator<CWINDOW> *); if (iter == NULL) { iter = new QPtrDictIterator<CWINDOW>(CWindow::dict); ENUM(QPtrDictIterator<CWINDOW> *) = iter; } next = iter->current(); if (next == NULL) { delete iter; //ENUM(QPtrDictIterator<CWINDOW>) = NULL; GB.StopEnum(); return; } ++(*iter); GB.ReturnObject(next);END_METHODBEGIN_PROPERTY(CWINDOW_count) GB.ReturnInteger(CWindow::dict.count());END_PROPERTYBEGIN_METHOD(CWINDOW_get, GB_INTEGER id) QWidget *wid = QWidget::find(VARG(id)); //qDebug("id = %d wid = %p", PARAM(id), wid); if (wid != 0 && wid->isTopLevel()) { //qDebug("-> %p", CWidget::getReal(wid)); GB.ReturnObject(CWidget::getReal(wid)); } else { //qDebug("-> %p", 0); GB.ReturnNull(); }END_METHODstatic bool do_close(CWINDOW *_object, long ret, bool destroyed = false){ bool closed; if (CWIDGET_test_flag(THIS, WF_IN_CLOSE) || CWIDGET_test_flag(THIS, WF_CLOSED)) return false; if (!THIS->window) { CWIDGET_set_flag(THIS, WF_IN_CLOSE); closed = !GB.Raise(THIS, EVENT_Close, 0); CWIDGET_clear_flag(THIS, WF_IN_CLOSE); if (destroyed) { CWIDGET_set_flag(THIS, WF_CLOSED); } else if (closed) { CWIDGET_set_flag(THIS, WF_CLOSED); WINDOW->hide(); if (!CWIDGET_test_flag(_object, WF_PERSISTENT)) CWIDGET_destroy((CWIDGET *)THIS); } } else { if (WINDOW->isHidden()) { QCloseEvent e; QApplication::sendEvent(WINDOW, &e); closed = e.isAccepted(); } else closed = WINDOW->close(); } if (closed) THIS->ret = ret; //qDebug("CWINDOW_close: ret = %d", THIS->ret); return (!closed);}BEGIN_METHOD(CWINDOW_close, GB_INTEGER ret) long ret = VARGOPT(ret, 0); GB.ReturnBoolean(do_close(THIS, ret));END_METHODBEGIN_METHOD_VOID(CWINDOW_raise) if (!THIS->window) { if (!FRAME->isVisible()) FRAME->show(); FRAME->raise(); } else { if (!WINDOW->isVisible()) WINDOW->showActivate(); else WINDOW->raise(); }END_METHODBEGIN_METHOD_VOID(CWINDOW_show) if (!THIS->window) { FRAME->raise(); FRAME->show(); } else { //if (CWINDOW_Current) // GB.Error("A modal window is already displayed"); //else if (CWINDOW_Current) WINDOW->showModal(); else WINDOW->showActivate(); }END_METHODBEGIN_METHOD_VOID(CWINDOW_show_modal) THIS->ret = 0; if (!THIS->embedded) WINDOW->showModal(); //qDebug("CWINDOW_show_modal: ret = %d", THIS->ret); GB.ReturnInteger(THIS->ret);END_METHODBEGIN_PROPERTY(CWINDOW_modal) if (!THIS->embedded) GB.ReturnBoolean(WINDOW->isModal()); else GB.ReturnBoolean(false);END_PROPERTY/*BEGIN_METHOD_VOID(CWINDOW_dialog) CWINDOW *win; GB.New((void **)&win, GB.GetClass(NULL), NULL, NULL); win->ret = 0; ((MyMainWindow *)win->widget.widget)->showModal(); GB.ReturnInteger(win->ret);END_METHOD*/BEGIN_PROPERTY(CWINDOW_persistent) /* if (READ_PROPERTY) GB.ReturnBoolean(WIDGET->isPersistent()); else WIDGET->setPersistent(PROPERTY(char) != 0); */ if (!THIS->window) { if (READ_PROPERTY) GB.ReturnBoolean(true); } else { if (READ_PROPERTY) GB.ReturnBoolean(CWIDGET_test_flag(THIS, WF_PERSISTENT)); else { if (VPROP(GB_BOOLEAN)) CWIDGET_set_flag(THIS, WF_PERSISTENT); else CWIDGET_clear_flag(THIS, WF_PERSISTENT); } }END_PROPERTYBEGIN_PROPERTY(CWINDOW_text) if (!THIS->window) { if (READ_PROPERTY) GB.ReturnNull(); } else { if (READ_PROPERTY) GB.ReturnNewZeroString(TO_UTF8(WINDOW->caption())); else WINDOW->setCaption(QSTRING_PROP()); }END_PROPERTYBEGIN_PROPERTY(CWINDOW_menu_count) if (THIS->menu) GB.ReturnInteger(THIS->menu->count()); else GB.ReturnInteger(0);END_PROPERTYBEGIN_METHOD_VOID(CWINDOW_menu_next) CWINDOW *window = OBJECT(CWINDOW); unsigned int index; if (window->menu == NULL) { GB.StopEnum(); return; } index = ENUM(int); if (index >= window->menu->count()) { GB.StopEnum(); return; } GB.ReturnObject(window->menu->at(index)); ENUM(int) = index + 1;END_PROPERTY/*BEGIN_METHOD(CWINDOW_toolbar_add, CTOOLBAR *toolbar) QMainWindow *wid = WIDGET; QToolBar *tb = QTOOLBAR(PARAM(toolbar)); qDebug("ToolBar H = %d", tb->height()); wid->addToolBar(tb); qDebug("ToolBar H = %d", tb->height());END_METHODBEGIN_METHOD(CWINDOW_toolbar_remove, CTOOLBAR *toolbar) QMainWindow *wid = WIDGET; wid->removeToolBar(QTOOLBAR(PARAM(toolbar)));END_METHOD*/BEGIN_PROPERTY(CWINDOW_id) if (!THIS->window) GB.ReturnInteger(0); else GB.ReturnInteger((long)WINDOW->winId());END_PROPERTYBEGIN_PROPERTY(CWINDOW_border) if (!THIS->window) { if (READ_PROPERTY) GB.ReturnInteger(0); } else { if (READ_PROPERTY) GB.ReturnInteger(WINDOW->getBorder()); else WINDOW->setBorder(VPROP(GB_INTEGER)); }END_PROPERTYBEGIN_PROPERTY(CWINDOW_icon) if (!THIS->window) { if (READ_PROPERTY) GB.ReturnNull(); } else { if (READ_PROPERTY) GB.ReturnObject(THIS->icon); else SET_PIXMAP(WINDOW->setIcon, &(THIS->icon), PROP(GB_OBJECT)); //WIDGET->setIcon(PICTURE_set(&(THIS->icon), PROPERTY(CPICTURE *))); }END_PROPERTYBEGIN_PROPERTY(CWINDOW_mask) if (THIS->embedded) { if (READ_PROPERTY) GB.ReturnNull(); } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -