aboutsummaryrefslogtreecommitdiff
path: root/src/popup.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/popup.c')
-rw-r--r--src/popup.c232
1 files changed, 232 insertions, 0 deletions
diff --git a/src/popup.c b/src/popup.c
new file mode 100644
index 0000000..c9caafc
--- /dev/null
+++ b/src/popup.c
@@ -0,0 +1,232 @@
+/****************************************************************************
+ * Functions for displaying popup windows.
+ * Copyright (C) 2004 Joe Wingbermuehle
+ ****************************************************************************/
+
+#include "jwm.h"
+#include "popup.h"
+#include "main.h"
+#include "color.h"
+#include "font.h"
+#include "screen.h"
+#include "cursor.h"
+#include "error.h"
+#include "timing.h"
+#include "misc.h"
+
+#define DEFAULT_POPUP_DELAY 600
+
+typedef struct PopupType {
+ int isActive;
+ int x, y; /* The coordinates of the upper-left corner of the popup. */
+ int mx, my; /* The mouse position when the popup was created. */
+ int width, height;
+ char *text;
+ Window window;
+} PopupType;
+
+static PopupType popup;
+static int popupEnabled;
+int popupDelay;
+
+static void DrawPopup();
+
+/****************************************************************************
+ ****************************************************************************/
+void InitializePopup() {
+ popupDelay = DEFAULT_POPUP_DELAY;
+ popupEnabled = 1;
+}
+
+/****************************************************************************
+ ****************************************************************************/
+void StartupPopup() {
+ popup.isActive = 0;
+ popup.text = NULL;
+ popup.window = None;
+}
+
+/****************************************************************************
+ ****************************************************************************/
+void ShutdownPopup() {
+ if(popup.text) {
+ Release(popup.text);
+ popup.text = NULL;
+ }
+ if(popup.window != None) {
+ JXDestroyWindow(display, popup.window);
+ popup.window = None;
+ }
+}
+
+/****************************************************************************
+ ****************************************************************************/
+void DestroyPopup() {
+}
+
+/****************************************************************************
+ * Show a popup window.
+ * x - The x coordinate of the popup window.
+ * y - The y coordinate of the popup window.
+ * text - The text to display in the popup.
+ ****************************************************************************/
+void ShowPopup(int x, int y, const char *text) {
+
+ unsigned long attrMask;
+ XSetWindowAttributes attr;
+ const ScreenType *sp;
+
+ Assert(text);
+
+ if(!popupEnabled) {
+ return;
+ }
+
+ if(popup.text) {
+ Release(popup.text);
+ popup.text = NULL;
+ }
+
+ if(!strlen(text)) {
+ return;
+ }
+
+ popup.text = CopyString(text);
+
+ popup.height = GetStringHeight(FONT_POPUP);
+ popup.width = GetStringWidth(FONT_POPUP, popup.text);
+
+ popup.height += 2;
+ popup.width += 8;
+
+ sp = GetCurrentScreen(x, y);
+
+ if(popup.width > sp->width) {
+ popup.width = sp->width;
+ }
+
+ popup.x = x;
+ popup.y = y - popup.height - 2;
+
+ if(popup.width + popup.x >= sp->width) {
+ popup.x = sp->width - popup.width - 2;
+ }
+ if(popup.height + popup.y >= sp->height) {
+ popup.y = sp->height - popup.height - 2;
+ }
+
+ if(popup.window == None) {
+
+ attrMask = 0;
+
+ attrMask |= CWEventMask;
+ attr.event_mask
+ = ExposureMask
+ | PointerMotionMask | PointerMotionHintMask;
+
+ attrMask |= CWSaveUnder;
+ attr.save_under = True;
+
+ attrMask |= CWBackPixel;
+ attr.background_pixel = colors[COLOR_POPUP_BG];
+
+ attrMask |= CWBorderPixel;
+ attr.border_pixel = colors[COLOR_POPUP_OUTLINE];
+
+ attrMask |= CWDontPropagate;
+ attr.do_not_propagate_mask
+ = PointerMotionMask
+ | ButtonPressMask
+ | ButtonReleaseMask;
+
+ popup.window = JXCreateWindow(display, rootWindow, popup.x, popup.y,
+ popup.width, popup.height, 1, CopyFromParent,
+ InputOutput, CopyFromParent, attrMask, &attr);
+
+ } else {
+ JXMoveResizeWindow(display, popup.window, popup.x, popup.y,
+ popup.width, popup.height);
+ }
+
+ popup.mx = x;
+ popup.my = y;
+
+ if(!popup.isActive) {
+ JXMapRaised(display, popup.window);
+ popup.isActive = 1;
+ } else {
+ DrawPopup();
+ }
+
+}
+
+/****************************************************************************
+ ****************************************************************************/
+void SetPopupEnabled(int e) {
+ popupEnabled = e;
+}
+
+/****************************************************************************
+ ****************************************************************************/
+void SetPopupDelay(const char *str) {
+
+ int temp;
+
+ if(str == NULL) {
+ return;
+ }
+
+ temp = atoi(str);
+
+ if(temp < 0) {
+ Warning("invalid popup delay specified: %s\n", str);
+ } else {
+ popupDelay = temp;
+ }
+
+}
+
+/****************************************************************************
+ ****************************************************************************/
+void SignalPopup(const TimeType *now, int x, int y) {
+
+ if(popup.isActive) {
+ if(abs(popup.mx - x) > 2 || abs(popup.my - y) > 2) {
+ JXUnmapWindow(display, popup.window);
+ popup.isActive = 0;
+ }
+ }
+
+}
+
+/****************************************************************************
+ ****************************************************************************/
+int ProcessPopupEvent(const XEvent *event) {
+
+ if(popup.isActive && event->xany.window == popup.window) {
+ if(event->type == Expose) {
+ DrawPopup();
+ return 1;
+ } else if(event->type == MotionNotify) {
+ JXUnmapWindow(display, popup.window);
+ popup.isActive = 0;
+ return 1;
+ }
+ }
+
+ return 0;
+
+}
+
+/****************************************************************************
+ ****************************************************************************/
+void DrawPopup() {
+
+ Assert(popup.isActive);
+
+ JXClearWindow(display, popup.window);
+ RenderString(popup.window, FONT_POPUP, COLOR_POPUP_FG, 4, 1,
+ popup.width, NULL, popup.text);
+
+}
+